document.getElementsByClassName Example
(function(childNodes){
/* Another (C) WebReflection Silly Idea */
// how to re-use them all, just an example
if(!document.getElementsByClassName)
document.getElementsByClassName = function getElementsByClassName(className){
for(var
re = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"),
ret = [], i = 0, l = 0, length = childNodes.length, node;
i < length; ++i
){
if((node = childNodes[i]).nodeType === 1 && re.test(node.className))
ret[l++] = node
;
};
return ret;
}
;
// let the magic happen
})(document.getElementsByTagName("*"));
What we have here?
- A trapped live object, probably used in 90% of selector libraries, but performed via scope resolution (the document) and a function execution (the getElementsByTagName method) over all nodes ("*")
- a theoretically zero performances impact to retrieve again every node, being live there is no need to refresh it, and being trapped run-time, it will contain few nodes during the first execution
- a single scope able to create N functions based on one of the most common created HTMLCollection
What do you think?
13 comments:
Nice approach. Cool way to write your for loop also.
I like the thought process here. Good idea.
@fearphage thanks again for the nodeType suggestion (and the silly typo for the className) :D
Cheers guys
Hey I don't understand the regex
(?:\\s|^) doesn't that mean you're checking for character before the beg. of the line?
Any benchmarks yet?
Samer, that means look for a space or it starts with and look for a space after or it ends with.
The question mark is to avoid RegExp result cache.
Aaraon, not yet, what I expect is better loop performances, what I need to test, is if a wrapped live collection, the biggest one, slows down somehow the angine a la DOMNodeInserted. I think no, but I am not sure yet.
Regards
OK, no slowdown at all, and actually no benefits as well. The problem is that I am basing my tests with wrong timers, so it's 0 or it's 15/16, I cannot truly understand if I it is worth it. In any case, as document.getElementsByClassName, it's really fast :D
Can you elaborate on the tests you're doing? I don't understand what you mean by "The problem is that I am basing my tests with wrong timers, so it's 0 or it's 15/16"
J% I am taking the classic W3C page used in Taskspeed and others tests.
I put the function on the top, zero differences.
Then I perform a couple of searches, and I take time for each search.
Under windows, timers are almost useless, cause the result for a call that took 8 ms, for example, will always e 15 or 16, and never 8. This problem has been explained in John Resig blog few months (years?) ago :)
I like your approach very much, thanks for sharing :)
It doesn't behave like a live collection... At least on IE8 SM. And it seems obvious to me, since ret is nothing more than an array.
Am I missing something?
If you want something like a static node list, you can check for querySelectorAll, which is provided by IE8 and should be a lot faster.
Massimo
you are missing the childNodes variables ... please read again, test, understand, and ask more if necessary. Regards
Sorry to post again after 4 months...
Yes, childNodes is indeed a live NodeList, but ret is just an Array. And we're just adding the matching elements to that array. So, the returned object is not a live list.
That's what I wanted to say.
IE8 still doesn't implement getElementsByClassName but implements querySelectorAll, so if you want to replicate getElementsByClassName you can use querySelectorAll instead, which return a non-live node collection.
I understand that's not the point of your idea, which is to create a scope where you can define every function you want that can make a good use of the live NodeList of all the elements.
So defining getElementsByClassName was just an example, I guess.
Post a Comment