I’ve been looking over a lot of Javascript code lately, mostly in the various AJAX libraries. It’s been interesting to see the ways in which the different projects are using the language to enable them to coexist peacefully.
Though, one such example I found was a simple function that I found at “Simon Wilson’s web site”:http://simon.incutio.com/. It solves the problem of having several Javascript modules fighting for the coveted @onload@ event in the <body> tag. I say coveted because there is only one of these events on an HTML page, and it is very important because this event is called only after the entire page is loaded. For a Javascript module, this is a good time to do an action like initialization because it guarantees that any called functions will be able to work on on a complete set of HTML tags, Javascript modules, images, etc.
h3. The Past
Before the widespread use of Javascript, the @onload@ function would simply be set in the HTML @@ tag on a page.:
. .
And if there were several methods to be called, you could make the @onload@ function more generic by using it to call other methods:
. .
But this only works well if you are the creator of all of the code which goes into a site.
h3. The Present
Now that we’re seeing a ton of development happening on the HTML-side of things, especially from the AJAX-world, it’s certain that folks will start using multiple Javascript modules on their sites and that some of these modules will want to get their piece of the @onload@ event.
However, a problem arises if a module isn’t careful about how it sets the @onload@ event. If it uses basic Javascript syntax it would effectively wipeout any previously defined @onload@ functions:
Enter in “Simon’s addLoadEvent function”:http://simon.incutio.com/archive/2004/05/26/addLoadEvent which uses Javascript closures wrapped in a decorator-like fashion to allow more than one function to be assigned to the ‘onload’ event at runtime.
This is the code listing pasted from Simon’s site:
function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function() { oldonload(); func(); } } } addLoadEvent(nameOfSomeFunctionToRunOnPageLoad); addLoadEvent(function() { /* more code to run on page load */ });
However, I will note that this solution is not a pure example of the decorator pattern because:
- The definition from my Head Start book states “The Decoration Pattern involves a set of decorator classes that are used to wrap concrete components.” In this example the concrete component, the very innermost function, is of the same class as the closure decorators – a function – and not of a separate object type.
-
Also the function objects get called themselves rather then a separate method on a class object. However, I think this would be ok if you consider each function having an equivalent to Python’s @call@ method. This method would then be the common interface between the objects.
In any event, pure Decorator or not, this is a clever way to use Javascript to solve this web problem and at least deserves a Decorator Honorable Mention.