Applying behaviour to a single object
If you haven't already done so, read the introduction before continuing.
Most people will be familiar with inline behaviour, such as:
<div onclick = ”alert ('some message')”>
However, it has been suggested (by Peter-Paul Koch) that just as style is best placed in an external .css file, which is then imported into the web page, behaviour too should be treated in the same way. You could create a separate .js file, which might look like this:
window.onload = function (){
set (‘target_div onclick showalert’);
}
function showalert (){
alert ('some message');
}
Import it into the page, and now an alert will appear whenever "target_div" is clicked.
The function set() is quite versatile. As well as CSS properties and values (see Setting an object's properties), it can take an event as its property and a function reference as its value, as in the example above.
Separating markup and behaviour has two advantages. Because the script triggered by the event resides in an external file the markup will be clean and meaningful. And the script applied can be as long and complicated as you like (it could even call other functions if required). I once wrote some code to open and close a submenu. Inline it would have looked like this:
<div onclick = "var thismenu = 'submenu' + this.number; var submenu = document.getElementById(thismenu); if (!elem){elem = submenu; elem.style.display = 'block';} else if (elem == submenu){ if (elem.style.display == 'block') elem.style.display = 'none'; else elem.style.display = 'block';} else {elem.style.display = 'none'; elem = submenu; elem.style.display = 'block';}">
Imagine trying to debug that, if you got one of the curly braces in the wrong place! The following, stored in an external file, is surely the way to go.
window.onload = function (){
set (‘target_div onclick showmenu’);
}
function showmenu(){
var thismenu = 'submenu' + this.number;
var submenu = document.getElementById(thismenu);
if (!elem){
elem = submenu;
elem.style.display = 'block';
}
else if (elem == submenu){
if (elem.style.display == 'block')
elem.style.display = 'none';
else
elem.style.display = 'block';
}
else {
elem.style.display = 'none';
elem = submenu;
elem.style.display = 'block';
}
}
Applying behaviour to multiple objects
Using the function set() I could apply behaviour to all objects of a particular class, as follows:
set (‘target_class onclick showalert’);
function showalert (){
alert (‘some message’);
}
As I mentioned above, set() can take an event as its property and a function reference as its value.
However, there are not going to be many occasions when I want a lot of objects all causing the same thing to happen when clicked. I’m more likely to want each to trigger a different event, or a different version of the same event.
Consider a page with a series of thumbnails. The first should open an image when clicked, the second another image, the third yet another image. If the thumbnails are of class “imagelink” I could use this instruction:
set (‘imagelink onclick showimage’);
to call an image display function when each one is clicked. The function itself might look like this:
var num, imagepath;
function showimage (){
num = this.number;
imagepath = “images/image” + num + ”.jpg”;
set ('imageholder src imagepath');
}
This requires a few words of explanation.
When set() is used to apply properties or behaviour to a series of objects selected by class name, each one is automatically numbered as it appears on the page - the first to 0, the second to 1 and so on. I can use the number associated with the object clicked to construct a path to the required image: image0.jpg, image1.jpg etc. As long as the thumbnails are in the right order in the markup, showimage() will always display the correct image.
Rather than building the image file path using the number associated with each imagelink object, I could have stored all the paths in an array and then used the number to look up the right one. This approach would also be useful if I wanted to display one of a series of information messages. Create the array:
var messagearray = new Array (
“This is the first info message”,
“This is the second info message”,
.
.
)
and then link it to a series of objects:
set (‘infolink onclick showmessage’);
function showmessage (){
var num = this.number;
alert (messagearray[num]);
}
It probably goes without saying, but I’ll say it anyway: make sure that there are as many messages, or images, as there are links!
You can use the object number in another way. You're designing a menu with sub-menus. When an item from the main menu is clicked, the appropriate sub-menu appears. So you make each of the menu items the same class (for example "mainitem"), and give each of the sub-menus a sequential id ("submenu0", "submenu1" and so on). You also set their display to "none". Now you can apply behaviour to the menu items as follow:
set ('mainitem onclick showmenu');
var menupath;
function showmenu (){
menupath = "submenu" + this.number
set ('menupath display block');
}
Since the selector can be a global variable, this approach is fine.