My New GetElementsByClass() + a Safari 3.1 Oddity
To make use of the native getElementsByClassName I rewrote my getElementsByClass function to use the method where possible.
Here's the code*:
function getElementsByClass(theClass,node) {
var classElements = [];
var i;
if ( node == null ) {
node = document
}
if (node.getElementsByClassName) {
var tempCollection = node.getElementsByClassName(theClass);
for (i = 0; i < tempCollection.length ; i++) {
classElements.push(tempCollection[i])
}
}
else {
var els = node.getElementsByTagName("*");
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+theClass+"(\\s|$)");
for (i = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements.push(els[i]);
}
}
}
return classElements;
};
The above code works as expected in Firefox 2, 3; IE 6,7,8, Opera 9.5 and Safari 2.
Interestingly it doesn't work in Safari 3.1. Safari supports the native getElementsByClassName, so one would expect it to work alongside Firefox 3 and Opera 9.5.
It does not.
Here's a sample. Click "start" and everything should go from blue to black (which means the class is removed from the LIs) and the numbers should read "10 0″. The 10 is the length of the collection returned by my function when the test starts. The 0 refers to the length after the test has run it's course and the class has been removed.
Safari 3.1 looks like this:
So the count is 10, even though there are 0 instances of the class in the DOM:

This is the code I'm running:
function testSafari() {
$("messages").innerHTML = getElementsByClass("sample").length;
var samples = getElementsByClass("sample");
for (i=0;i<samples.length;i++) {
removeClass(samples[i],"sample");
}
$("messages").innerHTML += " "+getElementsByClass("sample").length;
}
I've approached the problem from a few different angles (not exhaustive) and taking a quick look at the WebKit source it seems to me that Safari might be incorrectly caching the results of the getElementsByClassName call. I haven't had the time I would like to test this to see what might be happening in specific, but that's what it feels like.
Anyone know more about the guts of WebKit? Am I onto something? Or is my nonexistent Apple dev knowledge showing?
For the webdev crowd, anyone else seen anything like this? Is it something stupid that I'm doing that I'm just not seeing (and therefore not actually a bug)?
That's always my first assumption, but the native method works in both Opera and Firefox so I'm more confident than normal that the issue isn't my fault.
*I used to have support for a specific tag. When rewriting it I thought "I never use the tag argument, I'm dropping it." Of course, as soon as I did that one of my co-workers used the tag argument in a script he was writing for a site we were working on. I'll be adding the tag option back in.
Also, this version relies on support for Array.push(). Our little library adds it in with this:
if(!Array.prototype.push) {
function array_push() {
for(var i=0;i<arguments.length;i++){
this[this.length]=arguments[i]
};
return this.length;
}
Array.prototype.push = array_push;
}




