Web DevCenter
oreilly.comSafari Books Online.Conferences.
MySQL Conference and Expo April 14-17, 2008, Santa Clara, CA

Sponsored Developer Resources

Web Columns
Adobe GoLive
Essential JavaScript
Megnut

Web Topics
All Articles
Browsers
ColdFusion
CSS
Database
Flash
Graphics
HTML/XHTML/DHTML
Scripting Languages
Tools
Weblogs

Atom 1.0 Feed RSS 1.0 Feed RSS 2.0 Feed

Learning Lab






Modifying Styles
Pages: 1, 2

Coding Challenges

Coding the script was surprisingly difficult, given the hoopla surrounding the supposed excellent standards support in the latest browsers. Everything I tried at first had to be abandoned or recoded for one reason or another, due to a lack of support for a particular approach or property in one browser or another. Here is a short list of many of the problems were encountered.



  • selectorText not supported in NS6/Mozilla

    Ultimately, one of the methods our script provides (setStyleByTag()) was extremely difficult to implement in Netscape Navigator 6.0 or Mozilla, due to a lack of support for the selectorText property of the cssRules array. This lack of support is documented here.

    We hope that the Mozilla project will remedy this quickly, as disabling selectorText has the unfortunate side effect of also excluding its value from cssRules objects altogether. It is possible to read the entire rule and scan for the selector. However Internet Explorer 5.0 gives you the full cssText value (albeit with case-folded properties):

    Related Reading

    JavaScript: The Definitive Guide, 4th EditionJavaScript: The Definitive Guide, 4th Edition
    By David Flanagan
    Table of Contents
    Index
    Sample Chapter
    Full Description

    SPAN { FONT-SIZE: 12pt; }

    Navigator only gives the internal rule text, not the selector:

    font-size: 12pt

    Your only option is to grab the raw data from inside the STYLE tags and parse out your own alternate list of ruleset selectors, which is a pretty egregious kludge. This makes it difficult to process rulesets by selector, and since there is no standard capability for accessing rulesets by name (e.g., styleSheets[0].cssRules["H1"]) this missing feature of the DOM makes Netscape6/Mozilla far less powerful. I've included a workaround, based on code found in the Mozilla source, which creates an alternate list of selectors for comparison's sake, and which is only called in Netscape6/Mozilla.

  • hasAttributes() not supported by IE5/Mac

    An early version of the script used the hasAttributes() method of the Level 2 Core W3C DOM, to check for STYLE attributes in the elements we wished to modify, but it is not supported in Internet Explorer 5.0/Macintosh. An alternative was to use the attributes array.

  • childNodes.length not supported by IE5/Mac

    Another approach I tried involved the use of the childNodes property of the Level 1 Core W3C DOM, but it is not supported properly by Internet Explorer 5.0/Macintosh. Instead of returning a NodeList array, with a length property (useful for looping over all children of a given node) it returns a Boolean value with no length property.

  • No standard way to grab all elements without childNodes (can use getElementsByTagName("*") on some platforms)

    Due to the lack of a properly implemented childNodes property, it is difficult to loop over all elements in a document using standards-based code. Fortunately, the DOM method getElementsByTagName() accepts the "*" argument, which specifies that all document elements should be returned. This works properly in both Internet Explorer 5.0 and Netscape 6.0 on the Macintosh, but is not supported by Internet Explorer 5.x on Windows, so in order to work around this the script checks for support for document.all and uses that if it is found. If not, the script reverts to using the appropriate standard method.

  • getAttributeNode() for IE5, getAttribute() for Navigator

    According to the Level 1 Core W3C DOM, the getAttribute() method should return the string value of the attribute passed as an argument, and the getAttributeNode() method should return an Attr object. However, in Internet Explorer 5.0/Macintosh, the getAttributeNode() method returns a string, and the getAttribute() method returns a null value. In an early version of the script, we had a workaround for this problem that involved checking for both methods, getAttributeNode() first. In the end, we simply used the attributes array combined with the nodeName and nodeValue properties.

  • Case doesn't matter in getAttribute() call

    It doesn't appear to make any difference to either Macintosh browser whether you use

    getAttribute("STYLE")

    or

    getAttribute("style")

    for regular HTML documents, but depending on how an XHTML document is served, it may have an impact, as XHTML is case-sensitive (as are all XML documents).

    Using the Script

    The script contains several functions, discussed in detail below. The first three functions set styles, allowing you to discriminate between elements based on their ID, their CLASS, or their tag name. The second set of functions simply allows you to get the current style settings for each element.

    The simplest of these is setStyleById(), which takes an element ID, a CSS property, and a value, and sets that element's property to that value.

    setStyleById(ID, property, value)

    The second function takes a tag name (e.g., H1), a class name, a CSS property, and a value, and sets the style for all elements of that type (or for all elements, if passed the "*" specifier).

    setStyleByClass(type, class, property, value)

    View the source for styley.js here.

    The third function takes a tag name (e.g., H1), a CSS property, a value, and the final (and optional) Boolean argument, which specifies whether to modify the style for that element in the stylesheet or in the .style array of the element. Unfortunately, due to the lack of a functional selectorText property in Netscape6/Mozilla, the stylesheet mode of the function does not work.

    setStyleByTag(tagname, property, value, global)

    The second set of functions allows you to read the values of any CSS property for any element, based on the element name, ID, or CLASS selector, as above.

    getStyleById(ID, property)
    getStyleByClass(type, class, property)
    getStyleByTag(type, property)

    If the property is found, it is returned as a string. If not, the functions return null.

    A Demonstration of the Script

    Note that because these scripts use advanced DOM functionality, they will not work in any browser previous to the IE5/Netscape6/Mozilla generation. This includes Navigator 4.x, Internet Explorer 4.x, and other, older browsers. To ensure that your site provides for users of those browsers, consider using a browser sniffer or server-side logic to deliver different content to those browsers.

    Simply click on the buttons below to demonstrate the script.

    Here's a section within <span> tags.

    Here's another section within <span> tags.

    This section is within <span class="bodytext"> tags.

    This is another section within <span class="bodytext"> tags.

    This section is within <span class="sourcecode"> tags.

    This is another section within <span class="sourcecode"> tags.


    Return to the JavaScript and CSS DevCenter.