Webessence

Dynamically add javascript files

There are some caveats when dynamically adding SCRIPT tags. To know when the added script has been downloaded, you can use the following function. It makes use of the load event when available with a fallback to the readystatechange event. The callback has access to the SCRIPT tag (this) and the event object.

function includeScript(src, callback) {
var script = document.createElement("script");
// IE will download the script as soon as the attribute src is set.
script.setAttribute("src", src);

if (typeof script.onload !== "undefined") {
// Chrome, Firefox and IE9
script.onload = callback;
} else if (typeof script.readyState !== "undefined") {
// IE < 9
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback.call(script, window.event);
}
};
}

document.getElementsByTagName("head")[0].appendChild(script);
}

// this = SCRIPT element.
// e = event object.
function scriptLoaded(e) {
alert("I downloaded " + this.src + " and the event was: " + e.type);
}

To add a script and execute some code after the script has been downloaded:

includeScript("test.js", scriptLoaded);

As in the article http://www.blaze.io/technical/ies-premature-execution-problem/ is explained, always add the created SCRIPT element to an element that is already attached to the DOM (like the HEAD element).

Javascript | 2011-12-27 12:30:22 | Comments (0)

MySQL to CSV

With mysqldump you can only create a CSV file if you have permission (and access) to the database server filesystem. So if you have a remote database server, you can use the following:

mysql -u[username] -h[server] -p[password] -B
-e "select * from database.table"
--default-character-set=utf8 > dump.csv
No tags | 2011-12-16 12:24:12 | Comments (0)

Asynchronous execute script in PHP without fork

The usage of pcntl_fork in a webserver environment is not encouraged according the PHP documentation. As an alternative, you can use the following code:

exec("/usr/bin/php some_script.php > /dev/null &");
// Here you can do some more actions, while some_script.php
// is still executing.

Even if the caller script has ended, the some_script.php will still run. A drawback certainly is the lack of return value.

PHP | 2011-12-07 15:41:37 | Comments (0)

Practical self defining or lazy function definiton

In Javascript Patterns by Stoyan Stefanov I read about self defining functions (also called lazy function definition). Last day I was writing an event handler for the mousemove event. For Firefox, Chrome and IE9 I could use the pageX and pageY properties of the event object. Off course, in IE < 8 this did not work, so I had to use e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft. I didn't want to test for this property everytime in the mousemove event handler, for performance reasons. After some time, I realised I had created a self defining function:

var getPageXY = function(e) {
if ("pageX" in e) {
getPageXY = function(e) {
return {"x" : e.pageX, "y" : e.pageY}
};
return getPageXY(e);
} else {
getPageXY = function(e) {
return {
"x" : e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft,
"y" : e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop};
};
return getPageXY(e);
}
};

So the first time this function is called (in a mousemove event handler), this function rewrites itself, so the next time it is called, it just does what is has to do.

Javascript | 2011-11-26 20:23:07 | Comments (0)

Javascript templating

A slightly modified version of John Resigs brilliant script JavaScript Micro-Templating. The modifications are:

  • Replace most of the regular expressions by splits, so it is easier to understand (at least for me) and it looks to be just as fast as the original.
  • I added an AJAX handler, so you can have external templates compiled on the fly.
  • Some refactoring, like the cache and the way it gets the template (by ID or by AJAX).

Read more...

Javascript | 2011-11-19 10:32:43 | Comments (2)

MySQL safe-updates for dummies

I just executed an update without the WHERE clause, so I guess I'm still a dummy...

So the next time, I will connect with:

mysql -uusername -p --safe-updates

Or:

mysql -uusername -p --i-am-a-dummy
MySQL | 2011-11-17 14:23:12 | Comments (2)

MySQL GET_LOCK

An easy way to prevent overlapping of cron jobs, is using the GET_LOCK function from MySQL. This function has the following definition:

GET_LOCK(name_of_lock, timeout)

It tries to get the named lock name_of_lock for timeout seconds. It returns 1 when it gets the lock, 0 if it timed out and NULL when an error occurred. The lock gets released when you call RELEASE_LOCK, closes the connection or call another GET_LOCK (!). This lock is server wide. This means that any code that connects to the same database server and asks for the same lock, has to wait until you have released it.

A PHP example:

$lock = 0;
// The variable $con is a MySQL connection.
// Try to get the lock for 10 seconds.
$query = "SELECT GET_LOCK('my_lock', 10)";
if (($result = $con->query($query))) {
if (($row = $result->fetch_row())) {
$lock = $row[0];
}
}

if ($lock == 0) {
die("Can't get the lock.");
}

// Here we can do our thing.
// If a job is here, and another job is started, it will not get the lock.

// Here we release the lock.
$con->close();
MySQL, PHP | 2011-11-17 14:14:46 | Comments (0)

Javascript encapsulation

The jQuery library is a good source for learning. An example of namespacing a library with a "no conflict" functionality a la jQuery.

myLib = "I'm a string!";

(function(global, undefined) {
// Save old value (if there is one).
var _myLib = global.myLib;

// This is the place to add to the global context.
var myLib = global.myLib = {};

var privateVar = "This is a private var";

function privateFunction() {
return "This is a private function";
}

myLib.Customer = function(name, age) {
this.name = name;
this.age = age;
};

myLib.Customer.prototype.toString = function() {
return this.name + ", " + this.age + " years";
};

// Access the global scope.
myLib.setTitle = function(title) {
global.document.title = title;
};

myLib.noConflict = function() {
global.myLib = _myLib;
return myLib;
}
})(window);

To use it:

myLib.setTitle("Hello 1");
var newMyLib = myLib.noConflict();
alert("Ok");
newMyLib.setTitle("Hello 2");
alert(myLib); // I'm a string!

Some links:

Javascript | 2011-11-12 16:54:11 | Comments (0)

Responsive IMG loading

A very nice way to serve the correct images based on the device width (the width of the screen). A jQuery example can be seen at http://www.headlondon.com/our-thoughts/technology/posts/creating-responsive-images-using-the-noscript-tag, but I rewrote it to a little standalone script.

The idea is to wrap all IMG tags inside NOSCRIPT tags. So browsers with no javascript will show the default image. Add HTML5 data-attributes to the NOSCRIPT tag that hold the values of the SRC of the images you can serve, based on screen width.

For example:

<noscript data-src-small="cat-small.jpg" data-src-large="cat-large.jpg">
<img src="cat-small.jpg" />
</noscript>

Execute the script after the DOMContentLoaded event (or put it at the end of the document).

(function() {

var src = screen.width < 501 ? "data-src-small" : "data-src-large";

var noscripts = document.getElementsByTagName("noscript");
for (var i = 0; i < noscripts.length; i++) {
var noscript = noscripts[i];
var img = document.createElement("img");
img.setAttribute("src", noscript.getAttribute(src));
noscript.parentNode.replaceChild(img, noscript);
}

}();
Javascript | 2011-10-30 14:05:14 | Comments (1)

Javascript and MVC

See http://www.webessence.nl/lab/mvc/ for an example of a MVC architecture for a Javascript app. There are 3 views connected to the model.

The cons of the MVC is it is abstract en has overhead, so in simple applications, it is too much.

The pros are experienced when you have a large application, where there is a alot of synchronization to do. In the example above, I have 3 views of the same "Customer" model. If a customer is selected, the views are notified by the model and can update their own user interface. This way the application doesn't get more complicated if you add more views (widgets) to it.

There are many ways to implement a MVC model, but I use the following idea:

var Model = function() {
// Properties, like:
this.selectedCustomer = null;
this.customers = [];
// Events, for example:
this.selectedCustomerChanged = new ModelEvent();
// For implementation of ModelEvent, see example source.
};

// The view gets the model and optional a controller.
var View1 = function(model, controller) {
this.model = model;
this.controller = controller || new Controller(model);
// Build up the user interface for this view, for example a select list of customers:
var select = document.createElement("select");
// TODO: add customers as options (not shown here)...
// When the user selects a customer, call the controller:
select.onchange = function() {
var id = select.options[select.selectedIndex].value;
controller.onSelectedCustomerChanged(id);
};
// The view listens for events of the model, and will update it's user interface.
this.model.selectedCustomerChanged.attach(function() {
// Update your user interface, because the model says
// the selected customer has changed.
});
};

// The controller gets the model.
var Controller = function(model) {
this.model = model;
};

// The view calls this on the controller when a user selects a different customer
// in the select list.
Controller.prototype.onSelectedCustomerChanged = function(id) {
// 1) Update the model.
// 2) The model will fire an event after selecting the customer.
// 3) The view will be notified and updates its interface.
};

So in short it has the following characteristics:

  • A model knows nothing about the views and the controllers.
  • A view knows the model and the controller.
  • A controller knows the model.
  • A view listens to events from the model.
  • When a user does something (in the view), the view tells the controller. The controller calls the model.
  • There is one model, one controller but there can be more views (see example, where there are 3 views).
  • Sometimes it's tempting to combine the view and the controller, but in larger applications, it is best to divide them.
  • A view is a visual filter of the model.
  • If the user can not do anything (so the view is just for viewing...), then there is no need for a controller.

Very good examples (I use alot of them in mine):

Javascript | 2011-10-30 10:29:39 | Comments (0)