I’m sure this has been posted before on the web but i felt like writing my own version anyway, if you notice performance tweaks as such or anything else simply leave a comment below and I’ll alter the code.
Basically these days classes are the best way for managing any website as you can assign them to elements and specifically select those elements in the CSS just by associating it with the class name, JS is also a great tool for manipulating these elements as it allows us to select a whole group of them at once without the need to manually go through and find the elements. This is all good and well when it comes to use libraries such as jQuery but when you only need to write a small amount of JS you would need something more simple.
In modern browsers the document.getElementsByClassName method is available to use but in IE8 and below the story isn’t the same, to accomplish the exact same result in all browsers we simply need to emulate the method as a protoype of the Object object.
Object.prototype.getElementsByClassName = function(c) {}
Now we can just create this really simple prototype and not think twice about how it runs in moderns browsers but if we want to avoid using extra processing power we can wrap it in an IF statement and check to see if the method exists within the document object.
if (typeof document.getElementsByClassName === 'undefined') {
Object.prototype.getElementsByClassName = function(c) {}
}
Now you can see we have solved the processing issue by simply checking if the method exists and only bind the prototype when its needed, next what we need to do is select all the elements from the DOM which we can do by using document.getElementsByTagName('*') which has been standard in all browsers since IE5 so no need to worry about browser compatibility.
if (typeof document.getElementsByClassName === 'undefined') {
// If the current browser doesn't support the built in class method lets
// create our own to emulate it
Object.prototype.getElementsByClassName = function(c) {
// Collect all the elements in the DOM
var ele = document.getElementsByTagName('*'),
tmp = [],
reg = new RegExp(c, 'i');
};
}
You can see i have specified some other variables but ill get to those in a second, basically we have just told the browser we can to grab every element currently in the DOM no matter what it is. The other two variables you see are for storage and performance, when we iterate through the elements we are going to cache the object for each matched element to avoid memory leaks ask it can happen. The reason we are setting the regular expression outside of the loop is because we don’t want to waste precious resources we could be using elsewhere by declaring the same variable over and over again in the loop, this goes for any other variable that can play a role in a loop that only needs to be declared once.
Now what we need to do is build the loop that we scan each element in the page and check the class name if the attribute class exists and append the element object to the tmp array:
if (typeof document.getElementsByClassName === 'undefined') {
// If the current browser doesn't support the built in class method lets
// create our own to emulate it
Object.prototype.getElementsByClassName = function(c) {
// Collect all the elements in the DOM
var ele = document.getElementsByTagName('*'),
tmp = [],
reg = new RegExp(c, 'i');
for (var i = 0; i < ele.length; i++) {
// Cache the current element to prevent memory leaks
var e = ele[i];
if (typeof e.className !== 'undefined' && e.className.match(reg)) {
// To improve performance when appending a new array item use the length
// to increment the current index
tmp[tmp.length] = e;
}
}
return tmp;
};
}
Nothing to it right? Alright maybe if your new to JS it might be confusing so let me break it down, first we store the current element object as it improves performance we calling it multiple times within a loop. Next we check if the attribute or in this class element property className exists and if it does match it against the regular expression we setup earlier, next we store the element object in the tmp array but you will notice we use tmp.length which is a better way for performance as your not requesting the browser to determine the next interation of the loop. Once all that is done we simply return the array and from there we can use our normal JS declarations to request the elements with a class name of foo for example.
var foo = document.getElementsByClassName('foo'),
bar = document.getElementsByClassName('bar');
alert('Foo: ' + foo.length + '\nBar: ' + bar.length);
var a = document.getElementsByClassName('item');
alert('Items: ' + a.length);
So now that we have everything together you can play around with the code at Tinkerbin using the following link http://tinkerbin.com/tnHWOnTr, i hope you have enjoyed reading this as i thought it may help at least one developer in need.



