kyber and Pepe: Thanks for the ideas and links. I made a test page - there are two test links ("Test 1" and "Test 2") in the upper-left corner of the page. Here are my results.
Code:
Test 1, Original implementation, Elapsed times:
Op: 16,32,
FF: 16,31,46,
IE7: 78,125
IE6: 90,109,110,130
Test 2, Test implementation, Elapsed times:
Op: 0,15,16
FF: 0,15,16,
IE7: 78,94,109,110,125,
IE6: 90,110,150,
Browsers:
On WinXP: Opera 9.10, Firefox 2.0, IE 7.
On WinNT: IE 6.
Notes:
- The browsers must be cacheing something because it always
takes longer when a test is ran just after reloading the page.
- I clicked each test link repeatedly until the elapsed time
became more consistent.
- A zero elapsed time just means that it was too fast for my
simple timing technique to measure (I think).
Here's the test driver and the two functions:
Code:
function test(cls, num)
{
if (num == 1) { // Test 1
startTime = new Date().getTime();
xGetElementsByClassName(cls, document, '*',
function(e){
e.style.border = '1px dotted red';
}
);
var et1 = new Date().getTime() - startTime;
alert('Original implementation: ' + et1);/////
}
else { // Test 2
var startTime = new Date().getTime();
xGetElementsByClassName2(cls, document,
function(e){
e.style.border = '1px dotted blue';
}
);
var et2 = new Date().getTime() - startTime;
alert('Test implementation: ' + et2);/////
}
}
function xGetElementsByClassName(c,p,t,f) // original implementation
{
var r = new Array();
var re = new RegExp("(^|\\s)"+c+"(\\s|$)");
var e = p.getElementsByTagName(t);
// var e = xGetElementsByTagName(t,p); // See xml comments.
for (var i = 0; i < e.length; ++i) {
if (re.test(e[i].className)) {
r[r.length] = e[i];
if (f) f(e[i]);
}
}
return r;
}
function xGetElementsByClassName2(c,p,f) // test implementation
{
var e, i, r = new Array();
if (!p) p = document;
if (document.evaluate) {
var x = document.evaluate(".//*[contains(concat(' ', @class, ' '), ' " + c + " ')]", p, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (i = 0; i < x.snapshotLength; i++) {
r[r.length] = x.snapshotItem(i);
if (f) f(x.snapshotItem(i));
}
}
/*
else if (p.getElementsByClassName) { // FF3 ?
r = p.getElementsByClassName(c);
}
*/
else {
var re = new RegExp("(^|\\s)"+c+"(\\s|$)");
e = p.getElementsByTagName('*'); // not for IE5
for (i = 0; i < e.length; ++i) {
if (re.test(e[i].className)) {
r[r.length] = e[i];
if (f) f(e[i]);
}
}
}
return r;
}
Everyone's feedback and further browser tests would be very much appreciated
Bookmarks