It is nice to see a (really close) example of this
design pattern in action.
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. 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.
The Past
Before the widespread use of
Javascript, the
onload function would
simply be set in the HTML
<body> tag on a
page.:
<script type="text/javascript">
function myfunction() {
}
</script>
<body onload="myfunction();">
•
•
</body>
And if there were several methods to be called, you
could make the
onload function more
generic by using it to call other methods:
<script type="text/javascript">
function myfunction1() {
}
function myfunction2() {
}
function doOnload() {
myfunction1();
myfunction2();
}
</script>
<body onload="doOnload();">
•
•
</body>
But this only works well if you are the creator of all
of the code which goes into a site.
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:
<script type="text/javascript">
// inconsiderate-script.com module
•
•
window.onload = inconsiderate_function;
</script>
Enter in
Simon's
addLoadEvent function 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:
1. 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.
2. 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.