Posted: Tuesday March 25, 2008
With the advent of Safari 3.1 and the proclaimed support for new DOM methods (among which is getElementsByTagName) comes of course the let-down.
It would appear that getElementsByClassName is broken in Safari. It works great the first time but unfortunately its internal DOM registry don't get updated, so if one changes the class name that one has searched for, it is still registered and will be returned the next time the query is performed.
Consider the following HTML code:
function switchActive( x )
document.getElementById( 'animals' ).getElementsByClassName( 'active' ).removeAttribute( 'active' );
document.getElementById( 'animals' ).getElementsByTagName( 'li' )[x].setAttribute( 'class', 'active' );
switchActive( 1 );
switchActive( 2 );
This will break in Safari because the browser still thinks that the first LI element has the class active applied to it, so it never removes that class from the second LI element.
The work-around is to force Safari to refresh its DOM registry, perhaps by using cloneNode on the LI element from which the class is being removed.
Of course, the really annoying problem is that with libraries and scripts that try to implement a working getElementByClassName method by extending the Element object will now break as they will use Safari's native implementation (unless of course they update the checks to browser sniff for Safari). All round, this is a very annoying bug!