back to devpro   download
$e = (function(){
/** Essential Selector
 * @author          Andrea Giammarchi
 * @blog            WebReflection
 * @version         0.1.1
 * @compatibilty    vary on browser CSS selectors capabilities.
 *                  tested in IE6 to 8, FireFox, Opera, Chrome, Safari
 * @param   String      CSS selector
 * @param   HTMLElement optional context to use with selector (makes search faster)
 * @return  Array       a JavaScript Array with 0, 1, or more, found elements
 */
var slice   = Array.prototype.slice,
    div     = document.createElement("div");
try{slice.call(div.childNodes)}catch(e){
    slice = function(i){
        var result = [],
            length = this.length;
        while(i < length)
            result[i] = this[i++];
        return result;
    };
};
if(div.querySelectorAll){
    div = null;
    return function(selector, HTMLElement){
        return slice.call((HTMLElement || document).querySelectorAll(selector), 0);
    };
};
var id          = /^#[a-zA-Z0-9_\-]+$/,
    nodeName    = /^(\*|[a-zA-Z0-9]+)$/,
    className   = /^\.[a-zA-Z0-9_\-]+$/,
    TagClass    = /^(\*|[a-zA-Z0-9]+)\.[a-zA-Z0-9_\-]+$/,
    counter     = "_" + ("" + Math.random()).slice(2),      // kangax thinks it's better
    clean = function(result){
        var length = result.length;
        while(length)
            delete result[--length][counter];
        return result;
    },
    getElementsByClassName = div.getElementsByClassName ?
        function(className, HTMLElement){
            return slice.call(HTMLElement.getElementsByClassName(className), 0);
        }:
        function(className, HTMLElement){
            return getElementsByTagClass("*." + className, HTMLElement);
        }
    ,
    getElementsByTagClass = function(selector, HTMLElement){
        for(var
            split   = selector.split("."),
            childNodes = HTMLElement.getElementsByTagName(split.shift()),
            re      = new RegExp("(?:\\s|^)" + split.shift() + "(?:\\s|$)"),
            length  = childNodes.length,
            i       = 0,
            j       = 0;
            i < length; ++i
        ){
            HTMLElement = childNodes[i];
            if(re.test(HTMLElement.className))
                split[j++] = HTMLElement;
        };
        return split;
    },
    path = function path(HTMLElement){
        var parentNode  = HTMLElement.parentNode,
            result      = [HTMLElement.nodeName],
            i           = 0;
        while(parentNode && parentNode.nodeType != 9){
            result[++i] = parentNode.nodeName;
            parentNode = parentNode.parentNode;
        };
        return result.reverse().join(" ");    
    },
    querySelectorAll = document.defaultView && document.defaultView.getComputedStyle ?
        (function(style){
            return function(selector, HTMLElement){
                for(var
                    text    = HTMLElement === document ? "" : path(HTMLElement),
                    length  = selector.length,
                    i       = 0;
                    i < length;
                    ++i
                )
                    selector[i] = text.concat(" ", selector[i]);
                for(var
                    text = style.appendChild(document.createTextNode(
                        selector.join(",").concat("{counter-increment:", counter, ";}")
                    )),
                    defaultView = document.defaultView,
                    childNodes  = HTMLElement.getElementsByTagName(selector.length === 1 ? resolve(selector[0]) : "*"),
                    result      = [],
                    length      = childNodes.length,
                    i           = 0,
                    j           = 0,
                    tmp;
                    i < length;
                    ++i
                ){
                    tmp = childNodes[i];
                    if(-1 < defaultView.getComputedStyle(tmp, null).getPropertyValue("counter-increment").indexOf(counter))
                        result[j++] = tmp;
                };
                style.removeChild(text);
                return result;
            };
        })((document.getElementsByTagName("head")[0] || document.documentElement).appendChild(document.createElement("style"))):
        (function(style){
            return function(selector, HTMLElement){
                for(var
                    increment = "counter-increment:" + counter,
                    text    = HTMLElement === document ? "" : path(HTMLElement),
                    length  = selector.length,
                    i       = 0;
                    i < length;
                    ++i
                )
                    style.addRule(selector[i] = text.concat(" ", selector[i]), increment, -1);
                for(var
                    childNodes  = HTMLElement.getElementsByTagName(selector.length === 1 ? resolve(selector[0]) : "*"),
                    result      = [],
                    length      = childNodes.length,
                    i           = 0,
                    j           = 0,
                    tmp;
                    i < length;
                    ++i
                ){
                    tmp = childNodes[i];
                    if(tmp.currentStyle["counter-increment"] == counter)
                        result[j++] = tmp;
                };
                i       = 0;
                length  = selector.length;
                while(i < length)
                    style.removeRule(selector[i++]);
                return result;
            };
        })(document.createStyleSheet()),
    resolve = function(selector){                           // dean suggested a speed up
        selector = selector.split(" ").pop();
        return nodeName.test(selector) ? selector : TagClass.test(selector) ? selector.split(".").shift() : "*";
    },
    unique = function(childNodes){
        for(var
            result  = [],
            length  = childNodes.length,
            i       = 0,
            j       = 0,
            current;
            i < length;
            ++i
        ){
            current = childNodes[i];
            if(!current[counter]){
                current[counter] = true;
                result[j++] = current;
            };
        };
        return  clean(result);
    }
;
div[counter] = true;
try{
    delete div[counter];
}catch(e){
    clean = function(result){
        var length = result.length;
        while(length)
            result[--length].removeAttribute(counter);
        return result;
    };
};
div = null;
return function(selector, HTMLElement){
    for(var
        context = HTMLElement || document,
        split   = selector.split(/\s*,\s*/),
        length  = split.length,
        i       = 0,
        j       = 0,
        result  = [],
        ignore  = [],
        current, undefined;
        i < length;
        ++i
    ){
        current = split[i];
        switch(true){
            case    id.test(current):
                if(current = context.getElementById(current.substring(1)))
                    result.push(current);
                break;
            case    nodeName.test(current):
                result.push.apply(result, slice.call(context.getElementsByTagName(current), 0));
                break;
            case    className.test(current):
                result.push.apply(result, getElementsByClassName(current.substring(1), context));
                break;
            case    TagClass.test(current):
                result.push.apply(result, getElementsByTagClass(current, context));
                break;
            default:
                ignore.push(current);
                break;
        };
    };
    if(ignore.length)
        result.push.apply(result, querySelectorAll(ignore, context));
    return arguments.callee.duplicated === false ? unique(result) : result;
};
})();
back to devpro   download
Creative Commons License