Section G. Attributes


G. Attributes

Attributes are a bit odd. Although officially they're nodes, they are not fully-fledged parts of the document tree and do not appear in, for instance, the childNodes[] list of their parent node. Furthermore, many common HTML attributes, like the src of an <img> or the href of an <a>, are also JavaScript properties, which means you don't need the W3C DOM attribute methods to read or change them. Finally, the handling of attributes is the area of the W3C DOM that contains most browser incompatibilities, and only about 20% of this part of the specification actually works correctly in all browsers.

Attributes are always name/value pairs. Take a well-known attribute:

<img src="/books/1/521/1/html/2/pix/theImage.gif" /> 


The name of the attribute is src, and its value is "pix/theImage.gif". Unsurprisingly, all attributes have a name and a value property that give the name and value of the attribute.

Attributes, Properties, and Browser Compatibility

I do not treat any W3C DOM attribute method or property except for getAttribute() and setAttribute(), because most of them are subject to one browser bug or another (and therefore useless). You can study the W3C DOM browser-compatibility tables at www.quirksmode.org.


Getting and setting attributes

The W3C DOM has two more or less reliable attribute methods: getAttribute() and setAttribute(). The first one is used often, the second rather less.

getAttribute() requires an attribute name and returns the value of that attribute. setAttribute() requires an attribute name and value, and sets that attribute to the new value. Take this example:

<img src="/books/1/521/1/html/2/http://www.quirksmode.org/pix/logo.gif"  /> var imgEl = document.getElementById('test'); alert(imgEl.getAttribute('src')); imgEl.setAttribute('src', 'http://www.quirksmode.org/pix/logo2.gif'); 


You access the <img> and ask for its src attribute. The browser returns the value of this attribute, and therefore the alert says 'http://www.quirksmode.org/pix/logo.gif'. Then you set the src attribute to a new value, and the image changes.

If an attribute does not exist, getAttribute() returns null.

Custom attributes

getAttribute() and setAttribute() work on any attribute an HTML tag contains, even custom ones, i.e., attributes that are not officially a part of any (X)HTML specification. I take advantage of this fact in Textarea Maxlength, Usable Forms, and Form Validation. All three scripts require the HTML coder to use custom attributes to give the script instructions. We already discussed the use and dangers of custom attributes in 4B. In this chapter it's enough to say that any HTML attribute is available through getAttribute().

Limitations

Warning

Browser incompatibilities ahead


Unfortunately, these methods have a few problems in Explorer 6 and earlier. Many HTML tags have special attributes to store their inline styles (style) and their event handlers (onclick, onkeydown, etc.). In Explorer, these attributes cannot be read or set through getAttribute() and setAttribute(); in fact, weird bugs may occur if you try it.

The solution is to use the JavaScript properties style, onclick, onkeydown, etc. to read or set these attributes. In order to completely understand this, we first have to discuss the subtle difference between HTML attributes and JavaScript properties.

HTML attributes and JavaScript properties

Although superficially they might seem the same, and there is in fact considerable overlap, HTML attributes are not always equal to JavaScript properties.

Let's dissect a few lines from Sandwich Picker. Each <tr> in the document contain one sandwich. I need to know the price of this sandwich to calculate the total price when the user orders it. Because the purpose of the script is to change the placement of these <tr>s in the document, I want to attach the price of a sandwich to its <tr>. In that way, the price always remains easily available, wherever the <tr> may happen to be at a certain time.

Figure 8.16. All sandwiches below this header are priced at 2,00.


Sandwich prices are located in the header <tr>s of the third table. I put them in a custom attribute in the HTML. Note that this is an HTML attribute; it's hard-coded in the page's HTML.

<tr price="2.00">    <th colspan="5" >&euro; 2,00</th> </tr> 


Browser Incompatibilities

Some browsers (Explorer and Safari at the time of writing) equate HTML attributes and JavaScript properties, and allow you to use x[i].price and x[i].getAttribute('price') indiscriminately.

Other browsers see HTML attributes and JavaScript properties as different things. To keep your scripts cross-browser compatible, it's best to treat attributes and properties as distinct entities.


When the script encounters the price attribute, it sets this price to all following sandwiches, until it encounters a new price attribute.

[Sandwich Picker, lines 34-40, condensed]

if (containers[i].getAttribute('price'))     currentPrice = containers[i].getAttribute('price'); containers[i].price = currentPrice; 


The first two lines read the HTML custom attribute price and then set currentPrice to its value. The third line sets the JavaScript price property of the <tr> to the value of currentPrice.

Even though they share a name, the HTML custom attribute and the JavaScript property are different things. The HTML attribute is located in the document tree as an attribute node of the <tr>, while the JavaScript property belongs to the object that represents the <tr> and is not present in the document tree.

This is the general rule. There are, however, numerous exceptions.

Attribute/property mappings

Before W3C specified the DOM, JavaScript needed a way to access a few important HTML attributes, like the value of a form field or the src of an image. In order to do this without the as-yet-unspecified getAttribute() method, JavaScript's inventors decided to map certain properties of JavaScript objects to HTML attributes.

For instance, all image objects would have a JavaScript src property that was equal to the HTML src attribute. Therefore these two lines are the same, though only the second one works in older browsers:

imgEl.setAttribute('src', 'http://www.quirksmode.org/pix/logo2.gif'); imgEl.src = 'http://www.quirksmode.org/pix/logo2.gif'; 


It's important to note that this is not a general rule, but that the browser vendors have hand-picked certain important attributes and created JavaScript properties to match them. These attribute/property mappings are most often found in the areas that have been open to scripting influences since the beginning: form fields, links, and images.

Later on, the style attribute that holds all inline styles of an element, as well as all event handlers (like onclick and onkeydown), were added to this list of special attributes/properties.

Although the W3C DOM now offers general and unrestricted access to all attributes, these special properties have never been removed from JavaScript, since that would mean that old scripts would stop working.

The best way of getting and setting attributes

With all this theoretical knowledge, we can discuss the best way of getting and setting attributes. I myself use these guidelines:

  • If there is an attribute/property mapping, I use it. This especially goes for style and event handlers, since Explorer cannot get or set them through the W3C DOM methods.

  • If there is no attribute/property mapping, I use getAttribute() and setAttribute().

  • Under no circumstances do I use the attributes[] nodeList, which is supposed to contain all attributes but differs significantly per browser, or any other W3C DOM method. Their browser implementation is currently too buggy.



ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net