Article

Well-Behaved DHTML: A Case Study

Page: 1 2 3 4 5 Next

The solution, of course, is to give a special class to the labels we want to behave dynamically:

<style type=”text/css”>  
 label.dynamic {  
   display:none;  
   }  
</style>

The second task essentially requires that we loop over all the label elements on the page, check to see whether they have the correct class, and if they do, add event handlers to their associated field. We should also save a copy of the label text in a property of the field for easy access, and initialize the label display while we’re here.

This requires some knowledge of the document object model. If you’re rusty on the details, or never took the time to learn, you can brush up at the W3C. Browser vendors often have good resources as well (e.g. Microsoft, and Mozilla), although these are obviously skewed toward their own implementations.

In a perfect world, once we learned how the DOM works, we could use the following code to perform our task. It uses getElementsByTagName the getElementById methods, as well as the className property. Each of these is defined in DOM Level 1 – HTML.

This code also uses the addEventListener method from DOM Level 2 Events.

n setupLabels() {  
 // get all the labels on the entire page  
 var objLabels = document.getElementsByTagName("LABEL");  
 var objField;  
 
 for (var i = 0; i < objLabels.length; i++) {  
   // if the label is supposed to be dynamic...  
   if ("dynamicLabel" == objLabels[i].className) {  
     // get the field associated with it  
     objField = document.getElementById(objLabels[i].htmlFor);  
     // add event handlers to the onfocus and onblur events  
     objField.addEventListener(“focus”, focusDynamicLabel, false);  
     objField.addEventListener(“blur”, blurDynamicLabel, false);  
     // save a copy of the label text  
     objField._labelText = objLabels[i].firstChild.nodeValue;  
     // initialize the display of the label  
     objField.value = objField._labelText;  
   }  
 }  
}

However, this code won’t work for IE/windows because it isn’t fully DOM-compliant; it doesn’t support the DOM Level 2 Events Module. Instead, it supports a proprietary interface that does the same thing. As IE/windows has such a huge user base -- and one we’d like to have see our effect -- we add a small hack to our script to accommodate its different object model (note the changed lines are bold):

function setupLabels() {  
 // get all the labels on the entire page  
 var objLabels = document.getElementsByTagName("LABEL");  
 var objField;  
 
 for (var i = 0; i < objLabels.length; i++) {  
   // if the label is supposed to be dynamic...  
   if ("dynamicLabel" == objLabels[i].className) {  
     // get the field associated with it  
     objField = document.getElementById(objLabels[i].htmlFor);  
     // add event handlers to the onfocus and onblur events  
     addEvent(objField, "focus", focusDynamicLabel);  
     addEvent(objField, "blur", blurDynamicLabel);
 
     // save a copy of the label text  
     objField._labelText = objLabels[i].firstChild.nodeValue;  
     // initialize the display of the label  
     objField.value = objField._labelText;  
   }  
 }  
}  
 
function addEvent(objObject, strEventName, fnHandler) {  
 // DOM-compliant way to add an event listener  
 if (objObject.addEventListener)  
   objObject.addEventListener(strEventName, fnHandler, false);
 
 // IE/windows way to add an event listener  
 else if (objObject.attachEvent)  
   objObject.attachEvent("on" + strEventName, fnHandler);  
}

We can make this script run once the page is loaded by attaching to the window’s onload event with the same utility function.

addEvent(window, "load", setupLabels);

Now all we have to do is implement focusDynamicLabel and blurDynamicLabel. This is easy -- it’s just like the original code from our first dynamic label script. The only difference is that it should be generalized so the same function works for each dynamic label on the page.

In a fully DOM-compliant browser, we could use the target property of the event object (Also defined in DOM Level 2 Events) to obtain a reference to the element that fired the event, and manipulate it:

function focusDynamicLabel(event) {  
 // get the form field that fired this event  
 var elm = event.target;  
 // if it is currently displaying the label...  
 if (elm._labelText == elm.value) {  
   // ... turn it off  
   elm.value = "";  
 }  
}  
 
function blurDynamicLabel(event) {  
 // get the form field that fired this event  
 var elm = event.target;  
 // if it’s empty...  
 if ("" == elm.value) {  
   // ... display the label text  
   elm.value = elm._labelText;  
 }  
}

But once again, IE/windows implements this functionality slightly differently, using the property srcElement instead of the standardized target, and making the event object available through window.event instead of the standardized way of passing it implicitly to event handler functions.

We’ll need another small hack and helper function:

function focusDynamicLabel(event) {  
 // get the form field that fired this event  
 var elm = getEventSrc(event);  
 // if it is currently displaying the label...  
 if (elm._labelText == elm.value) {  
   // ... turn it off  
   elm.value = "";  
 }  
}  
 
function blurDynamicLabel(event) {  
 // get the form field that fired this event  
 var elm = getEventSrc(event);  
 // if it’s empty...  
 if ("" == elm.value) {  
   // ... display the label text  
   elm.value = elm._labelText;  
 }  
}  
 
function getEventSrc(e) {  
 // get a reference to the IE/windows event object  
 if (!e) e = window.event;  
 
 // DOM-compliant name of event source property  
 if (e.target)  
   return e. target;
 
 // IE/windows name of event source property  
 else if (e.srcElement)  
   return e.srcElement;  
}

Example C shows our work so far.

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links