Every shim I have seen for this function has used the IE-only CSS expression trick. While there's no denying it's effective, it's made useless if the browser is not IE and doesn't support querySelectorAll either.jQuery is out of the question, since I don't want to get a whole framework just to shim one tiny little function. So I went and wrote my own. I'd like to submit it for review, which may include optimisations.Please note that this is not a complete shim, only enough for what is frequently used:tag nameidclass nameattribute, presence and exact value matchdescendant combinatorchild combinatorThe code:if( typeof document.querySelector == undefined) {    document.querySelectorAll = function(sel) {        var sels = sel.split(,),            run = function(node,selector) {                var sel = selector.split(/[ >]+/), com = selector.match(/[ >]+/g) || [], s, c, ret = [node], nodes, l, i, subs, m, j, check, x, w, ok,                    as;                com.unshift( );                while(s = sel.shift()) {                    c = com.shift();                    if( c) c = c.replace(/^ +| +$/g,);                    nodes = ret.slice(0);                    ret = [];                    l = nodes.length;                    subs = s.match(/[#.[]?[a-z_-]+(?:='[^']+'|=[^]+)?]?/gi);                    m = subs.length;                    for( i=0; i<l; i++) {                        if( subs[0].charAt(0) == #) ret = [document.getElementById(subs[0].substr(1))];                        else {                            check = c == > ? nodes[i].children : nodes[i].getElementsByTagName(*);                            if( !check) continue;                            w = check.length;                            for( x=0; x<w; x++) {                                ok = true;                                for( j=0; j<m; j++) {                                    switch(subs[j].charAt(0)) {                                    case .:                                        if( !check[x].className.match(new RegExp(\\b+subs[j].substr(1)+\\b))) ok = false;                                        break;                                    case [:                                        as = subs[j].substr(1,subs[j].length-2).split(=);                                        if( !check[x].getAttribute(as[0])) ok = false;                                        else if( as[1]) {                                            as[1] = as[1].replace(/^[']|[']$/g,);                                            if( check[x].getAttribute(as[0]) != as[1]) ok = false;                                        }                                        break;                                    default:                                        if( check[x].tagName.toLowerCase() != subs[j].toLowerCase()) ok = false;                                        break;                                    }                                    if( !ok) break;                                }                                if( ok) ret.push(check[x]);                            }                        }                    }                }                return ret;            }, l = sels.length, i, ret = [], tmp, m, j;        for( i=0; i<l; i++) {            tmp = run(this,sels[i]);            m = tmp.length;            for( j=0; j<m; j++) {                ret.push(tmp[j]);            }        }        return ret;    };    document.querySelector = function(sel) {        var ret = this.querySelectorAll(sel);        if( ret.length > 0) return ret[0];        else return null;    };    if( typeof HTMLElement != undefined) {        HTMLElement.prototype.querySelector = document.querySelector;        HTMLElement.prototype.querySelectorAll = document.querySelectorAll;    }    else {        dommods_extend.push(function() {            var a = document.getElementsByTagName(*), l = a.length, i;            for( i=0; i<l; i++) {                a[i].querySelector = document.querySelector;                a[i].querySelectorAll = document.querySelectorAll;            }        });        // dommods_extend is an array of functions that are run whenever the DOM is updated,        // to apply changes such as auto-resizing textareas, default value for <select> and so on.    }}
querySelectorAll shim for non-IE browsers
javascript;cross browser
OveralI am not sure which non IE-browser doesn't support querySelectorAll. Regardless, the code seems very performant, if a little Golfic ( reminds me of code golf ).NitpickingsIf you wish this source to be maintained / debugged /reviewed by others, there are some things you can change to make that easier:Declare unassigned variables last. It is easier on the eyes to know when to stop reading that long var line.I am all for Spartan coding, but w,m,c (which is not a character!), l etc. just make for unmaintainable code.Make your regex's constants with a meaningful name, it will make your code easier to understand.Use new lines after the if conditionif/else branches should either both have curly braces, or both not have curly braces, dont mixYou could use Array.concat here://As isfor( i=0; i<l; i++) {    tmp = run(this,sels[i]);    m = tmp.length;    for( j=0; j<m; j++) {        ret.push(tmp[j]);    }}//Replacement proposalfor( i=0; i<l; i++)  ret.push( run(this,sels[i])  );You could use a trinary here ://As is if( ret.length > 0) return ret[0];else return null//Replacement proposalreturn ret.length?ret[0]:null;FinallyIt is considered bad practice to shim in incomplete implementations, if you want to add to the HTMLElement prototype, use your own names to remove any confusion. HTMLElement.prototype.darkQuerySelector sounds so much better anyway ;)