Get Elements By Class Name

31 August 2011

As getElementsByClassName isn’t widely supported (ie anyone? Fails in ie6, ie7, ie8) and I couldn’t introduce a library to the page; I needed to write a little function to find and return all elements that had a (single) classname.

The solution

function getElementsByClassName(root, classname, tag) {
     var nodes = [];
     if (root.getElementsByClassName) {
         return root.getElementsByClassName(classname);
     } else {
         each(root.getElementsByTagName(tag || '*'), function (el) {
             if (el.className)
                 if ((" " + el.className + " ").indexOf(" " + classname + " ") > -1) {
                     nodes.push(el);
             }
         });
         return nodes;
     }
}

This function will use the browser version (if available) then fall back to the custom code. So it iterates within the list of nodes with the supplied tag name till it finds the classname in question, and add’s it to the array, which is returned on complete. Because we want the whole classname, and not just a section of it, you can add a ” ” (space) delimiter on either side of the element in questions class and the class you’re looking for. I haven’t tested this for performance, but it should be more performant than a regex.test().

Each?

You may notice that the code references an each function. I had written it for another purpose, so i used it again, but it could easily be replaced by a for loop. This is the code for the each function.

function each(a, fn) {
    var i = 0, il = a.length;
    for(; i < il; i += 1) {
        fn(a[i], i, a);
    }
}

Without the each

If you didn’t have or want the each function, the code would look like this

function getElementsByClassName(root, classname, tag) {
    var nodes = [], tests, i, il;
    if (root.getElementsByClassName) {
        return root.getElementsByClassName(classname);
    } else {
        tests = root.getElementsByTagName(tag || '*');
        for(i = 0, il = tests.length; i < il; i += 1) {
            if (tests[i].className) 
                if ((" " + tests[i].className + " ").indexOf(" " + classname + " ") > -1) {
                    nodes.push(el);
            }
        };            
        return nodes;
    }
}

Matt Sain

Ramblings of a developer, designer and child subscribe

This blog is a public GitHub repository. If you find an error I will not be surprised... but if you fork and edit the blog and send me a pull request you'd be pretty awesome in my book.

Featured Repos