In Part One, we built a very simple page with a single button that made use of some Behavioral Action Model techniques. From part one, we had the following function that provided the muscle for our button:
function link()
{
var btn = document.getElementById("mybutton");
btn.onclick = function() { self.location = 'mypage.html'; }
}
This function was made available to the document by means of the body tag’s “onload” method. This works just fine for a few functions but breaks down rather quickly when the complexity begins to rise. Fear not though, the mechanism still applies. With a little coaxing and a touch JavaScript’s flexibility, we can continue undaunted.
For starters, it would more convenient if we didn’t need to actually create a “btn” reference from within the function. Something more like the following perhaps:
function link()
{
btn.onclick = function() { self.location = 'mypage.html'; }
}
We could then pass the “btn” reference in as an argument of the function:
function link(btn)
{
btn.onclick = function() { self.location = 'mypage.html'; }
}
To make all of this a bit more “generic”, let’s replace the “btn” name for something less specific, like “element”.
Rewriting the above function with our substitution yields the following.
function link(element)
{
element.onclick = function() { self.location = 'mypage.html'; }
}
At this point, we have returned to something extremely similar to our original “goto” function from part one:
function goto(url) { self.location = url; }
Although these two are similar, there are some major differences. While the latter “goto“, function is just that, a function. The former “link” function has evolved into JavaScript’s version of a class. This classifying, if you’ll pardon the expression, has created a class Link that contains an “onclick” method. We can add additional methods as well.
function Link(element)
{
element.onclick = function() { self.location = 'mypage.html'; };
element.onmouseover = function() { };
element.onmouseout = function() { };
}
The Link class now has some extra muscle that be applied to the element under differing contexts. It can now respond to “click“, “mouseover“, and “mouseout” events. This is fine, but how do we make use of this improved link function?
In part one, we used the onload method to install the script that directly bound itself to the element. This time we will inject a little abstraction into the mixture giving us a lot more flexibility. Instead of loading “Link” class directly, we’ll install a loader function that will in turn load this class. We still have an issue with the “Link” class itself. It is not directly bound to an element as it was originally, but rather accepts a reference to one instead. So, how do we tie our class to the desired element or elements?
In JavaScript, classes are Objects and can be thus be members of other Objects. We can in fact store our “Link” class with all its methods within another Object, like an array. This would give us the ability to
store many other classes; Luckily, JavaScript offers us not only an array but also an associative array (otherwise known as maps, or hashes). Why is this so lucky you ask?
Associative arrays are special in that the array stores data as key-value pairs where the key is literally the means to access the value. This is ideal for our purposes since the key can be a text string instead of a numerical index. Let’s use the “Link” class to illustrate this point.
function Link(element)
{
element.onclick = function() { self.location = 'mypage.html'; };
element.onmouseover = function() { };
element.onmouseout = function() { };
}
If we extract the class name to use as the key, namely “Link”. Then the contents of the class become the matching value. Since the key is text, it has been set into single quotes.
'Link' : function (element)
{
element.onclick = function() { self.location = 'mypage.html'; };
element.onmouseover = function() { };
element.onmouseout = function() { };
}
The colon denotes an associative pair. The text string on the left is the key; while, the remaining class definition becomes the value on the right hand side. Now that our class has been converted into a key-value pair, it needs to be added to a container Object. We’ll name our Object “bam_classes” and make the assignment as follows:
var bam_classes =
{
'Link' : function (element)
{
element.onclick = function() { self.location = 'mypage.html'; };
element.onmouseover = function() { };
element.onmouseout = function() { };
}
};
Having our class definition stored as a value tied to its function name as the key further adds a subtle layer of abstraction. Remember that the name is a text string and thus could be any string and not necessarily a traditional function or class name, like “myFunc” or “accountsPayable”. Pulling a quote from part One, …”any valid element tag, class,
attribute, or combination thereof can be used” brings us to an important juncture.
In part one, our button element was styled with the class “goLink” and had and id attribute of “mybutton“. There is no reason why we can’t use this information as the key for our class definition that is stored in the “bam_classes” Object. Fortunately, CSS provides a convenient nomenclature for just this case:
var bam_classes =
{
'button.goLink#mybutton' : function (element)
{
element.onclick = function() { self.location = 'mypage.html'; };
element.onmouseover = function() { };
element.onmouseout = function() { };
}
};
Having the ability to use CSS selectors as the key for stored classes is a major step forward in both expressive power and the extraction of control and logic code from presentation code. We can now tie functionality to elements as broadly as all buttons, or as discretely as button of “some_class” that has an id of “some_id“
Finally, we have reached the point where we jump back to the loader function that is being called in the body’s “onload” method. The purpose of the loader class is to attach all our functionality encapsulated in the bam_classes Object to their corresponding elements. The loader extracts the keys from the bam_classes Object then parses through the DOM elements within the document looking for matches. Each matched element becomes a reference that is used by the attached function.
{end part two}