zoukankan      html  css  js  c++  java
  • dom Framework query模块

    我自行开发、引以为豪的CSS3选择器,jQuery能支持的选择器基本都支持了,除了那个:has伪类外。由于选择器种类繁多,也不太好演示,因此请下载文档回来看吧。

    用法基本与jQuery一样,下面是一个简单示例:

        dom.ready(function(){
            dom(".sample :hidden").each(function(){
              if(this.type){
                dom.console.log(this.tagName+"  "+this.type)
              }else{
                dom.console.log(this.tagName)
              }
            });
        });
    

    源码:

     
    /*dom Framework version 1.0
    Copyright 2010
    Dual licensed under the MIT or GPL Version 2 licenses.
    author: <ruby> <rb>司徒正美<rp>(zhongqincheng)</rp></rb><rt>しとぅなさみ</rt></ruby>
    http://www.cnblogs.com/rubylouvre/
    */
    //=========================================
    // 选择器模块
    //==========================================
    ;;;(function(dom,window,undefined){
        dom.provide("query");
        dom.lib.quickTag = false;
        dom.lib.isNot = false;
        dom.lib.pageOrder = ("sourceIndex" in document.documentElement) ?  function (a, b) {
            return (a.sourceIndex - b.sourceIndex);
        }:function (a, b) {
            return (3 - (a.compareDocumentPosition(b) & 6));
        };
        var getUIDXML = function(node){
            var uid = node.getAttribute(dom.expando);
            if (!uid){
                uid = dom.uuid++
                node.setAttribute(dom.expando, uid);
            }
            return uid;
        };
        var getUIDHTML = function(node){
            return node.uniqueNumber || (node.uniqueNumber = dom.uuid++);
        };
        //用于获取选择器的类型
        var types_ = {
            "#":"id",        //ID选择器
            ".":"class",     //类选择器
            /*"tag";         //标签选择器*/
            "[":"attribute", //属性选择器
            " ":"descendant",//关系选择器(后代选择器)
            ">":"child",     //关系选择器(亲子选择器)
            "+":"adjacent",  //关系选择器(相邻选择器)
            "~":"general",   //关系选择器(兄长选择器)
            ":":"pseudo",    //伪类选择器
            ",":"combine",   //联合选择器
            "*":"wildcard"   //通配符选择器
        }
        //用于移除相应的选择器
        var regexes_ = {
            id: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,      //ID选择器
            tag: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,   //标签选择器
            attribute: /\[((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)(['"]*)(.*?)\3|)\]/, //属性选择器
            "class": /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,//类选择器
            pseudo: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/, //伪类选择器
            combine: /,/,                               //联合选择器
            child:/^(\>)\s*(\w*|\*)/,                    //亲子选择器
            adjacent:/^(\+)\s*(\w*|\*)/,                 //相邻选择器
            general:/^(\~)\s*(\w*|\*)/,                  //兄长选择器
            descendant: /\s+(\.((?:[\w\u00c0-\uFFFF_-]|\\.)+))?/,            //后代选择器
            wildcard :/\*/                               //通配符选择器
        };
        var queryPseudoHasExp = function(start_,next_,noCheck_){
            return {
                curry :function(lastResult,flag,a ,b){
                    //将外围变量变成本地变量
                    var start = start_,next = next_, isAll = noCheck_,
                    result = [],ri = 0, uniqResult = {},
                    i = 0, n = lastResult.length, el, uid, find;
                    while (i < n) {
                        el = lastResult[i++];
                        uid = flag.uuid(el),
                        find = uniqResult[uid];
                        if (find === void 0) {
                            for (var c = 0, node = el.parentNode[start], nodeName = el.nodeName;node; node = node[next])
                                if (node.nodeType === 1 && (isAll || nodeName === node.nodeName)) {
                                    ++c;
                                    uniqResult[flag.uuid(node)] = a === 0 ? c === b : (c - b) % a === 0 && (c - b) / a >= 0;
                                }
                            find = uniqResult[uid];
                        }
                        if (find ^ dom.lib.isNot)
                            result[ri++] = el;
                    }
                    return result;
                }
            }
        }
    
        var queryPseudoNoExp = function(_direction,_noCheck){
            return {
                curry : function(lastResult){
                    var result = [],ri = 0,els = lastResult,direction = _direction,isAll = _noCheck;
                    for (var i = 0, el; el = els[i]; i++) {
                        var tagName = isAll || el.nodeName, find = null
                        if (find === null && direction <= 0){
                            for (var node = el.previousSibling; node; node = node.previousSibling)
                                if (node.nodeType === 1 && (isAll || node.nodeName === tagName)) {
                                    find = false;
                                    break;
                                }
                        }
                        if (find === null && direction >= 0)
                            for (var node = el.nextSibling; node; node = node.nextSibling)
                                if (node.nodeType === 1 && (isAll || node.nodeName === tagName)) {
                                    find = false;
                                    break;
                                }
                        if (find === null)//如果本身就是first-child或last-child
                            find = true;
                        if (find ^ dom.lib.isNot)//参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。
                            result[ri++] = el;
                    }
                    return result;
                }
            }
        }
    
        var filters = { //伪类选择器的过滤器
            enabled: function(el){//标准
                return el.disabled === false && el.type !== "hidden";
            },
            disabled: function(el){//标准
                return el.disabled === true;
            },
            checked: function(el){//标准
                return el.checked === true;
            },
            indeterminate:function(el){//标准
                return el.indeterminate = true && el.type === "checkbox"
            },
            selected: function(el){
                el.parentNode.selectedIndex;
                return el.selected === true;
            },
            empty: function (el) {//标准
                return !el.firstChild;
            },
            lang: function (el, value) {//标准
                var reg = new RegExp("^" + value, "i")
                while (el && !el.getAttribute("lang"))
                    el = el.parentNode;
                return  !!(el && reg.test(el.getAttribute("lang")));
            },
            header: function(el){
                return /h\d/i.test( el.nodeName );
            },
            button: function(el){
                return "button" === el.type || el.nodeName === "BUTTON";
            },
            input: function(el){
                return /input|select|textarea|button/i.test(el.nodeName);
            },
            hidden : function( el ) {
                dom.require("node");
                return el.type === "hidden" || dom.getStyle(el,"display") === "none"
            },
            visible : function( el ) {
                dom.require("node");
                return el.type !== "hidden" && dom.getStyle(el,"display") !== "none"
            },
            link:function(el){
                return el.nodeName.toLowerCase() === "a";
            },
            root:function(el,exp,context){//标准
                return el ===  context.documentElement;
            },
            target:function(el,exp,context){//标准
                var id = context.location.hash.slice(1);
                return (el.id || el.name) === id;
            },
            parent : function( el ) {
                return !!el.firstChild;
            },
            contains: function(el, exp) {
                return (el.textContent||el.innerText||'').indexOf(exp) !== -1
            },
            "first-child":      queryPseudoNoExp(-1, true),//标准
            "last-child":       queryPseudoNoExp( 1, true),//标准
            "only-child":       queryPseudoNoExp( 0, true),//标准
            "first-of-type":    queryPseudoNoExp(-1, false),//标准
            "last-of-type":     queryPseudoNoExp( 1, false),//标准
            "only-of-type":     queryPseudoNoExp( 0 ,false),//标准
            "nth-child":        queryPseudoHasExp("firstChild", "nextSibling",     true),//标准
            "nth-last-child":   queryPseudoHasExp("lastChild",  "previousSibling", true),//标准
            "nth-of-type":      queryPseudoHasExp("firstChild", "nextSibling",     false),//标准
            "nth-last-of-type": queryPseudoHasExp("lastChild",  "previousSibling", false),//标准
            //与位置相关的过滤器
            first: function(index){
                return index === 0;
            },
            last: function(index, num){
                return index === num;
            },
            even: function(index){
                return index % 2 === 0;
            },
            odd: function(index){
                return index % 2 === 1;
            },
            lt: function(index, num){
                return index < num;
            },
            gt: function(index, num){
                return index > num;
            },
            eq: function(index, num){
                return index ===  num;
            }
        };
        dom.each(String("text radio checkbox file password submit image reset").match(/\w+/g),
            function(name){
                filters[name] = function(el){
                    return el.type === name
                }
            });
    
        var parseNth = function (exp) {
            var match = /(-?)(\d*)n([-+]?\d*)/.exec(exp === "even" && "2n" || exp === "odd" && "2n+1" || !/\D/.test(exp) && "0n+" + exp || exp);
            return {
                a: (match[1] + (match[2] || 1)) - 0,
                b: match[3] - 0
            };
        };
    
        var _position = dom.oneObject(String("eq gt lt first last even odd").match(/\w+/g));
    
        //http://www.cnblogs.com/rubylouvre/archive/2009/11/25/1610044.html
        dom.queryId = function (id, context) {
            var el = (context || document).getElementById(id);
            return el && [el] || []
        };
        if(dom.env.mixupsName){
            //如果浏览器的getElementById不能区分name与id
            dom.queryId = function(id,root){
                root = root || document;
                var el = root.getElementById(id);
                if (el && el.attributes['id'].value === id) {
                    return [el]
                } else {
                    var all = root.all[id];
                    for(var i=0;el=all[i++];){
                        if(el.attributes['id'].value === id)
                            return [el]
                    }
                    return []
                }
            }
        }
    
        var queryWildcard = function (root) {//获得页面上或者某个元素节点下的所有元素
            var all =  root.all || root.getElementsByTagName("*"),result;
            if(dom.ie){
                result = dom.filter(all,function(el){
                    return el.nodeType === 1
                });
                if(dom.env.traverseAllElements)
                    dom.merge(result,(root.getElementsByTagName("param") || []))
                return result;
            }else{
                return dom.slice(all);
            }
        };
    
        var queryTag = function(tagName, lastResult, tools){
            var result = [],ri = 0, n = lastResult.length, uniqResult = {},nodes;
            if(dom.lib.isNot){
                var all = n ? lastResult :queryWildcard(tools.context);
                return dom.filter(all,function(el){
                    return el.tagName !== tagName;
                });
            }
            if (n === 0) {
                return dom.slice(tools.context.getElementsByTagName(tagName))
            } else {
                var i = 0 ,j ,jn ,node ,uid ;
                if(dom.lib.quickTag ){
                    dom.lib.quickTag = false;
                    while(i < n){
                        nodes = lastResult[i++].getElementsByTagName(tagName);
                        j = 0;
                        jn = nodes.length;
                        while(j < jn){
                            node = nodes[j++];
                            uid = tools.uuid(node);
                            if(uniqResult[uid] !== node){
                                result[ri++] = uniqResult[uid] = node;
                            }
                        }
                    }
                    return result;
                }else{
                    while(i < n){
                        node = lastResult[i++];
                        if(node.nodeName === tagName )
                            result[ri++] = node;
                    }
                    return result;
                }
            }
        }
    
        var queryClass = function (className, lastResult, tools) {
            var result = [],ri = 0,i = 0, n = lastResult.length, el,
            reg =  new RegExp('(?:^|[ \\t\\r\\n\\f])' + className + '(?:$|[ \\t\\r\\n\\f])');
            if (n === 0) {//查找模式
                if (tools.byClass) {
                    return Array.prototype.slice.call(tools.context.getElementsByClassName(className));
                } else {
                    var els = tools.context.all || tools.context.getElementsByTagName("*");
                    for(i=0;el=els[i++];){
                        if(reg.test(el.className || el.getAttribute("class")))
                            result[ri++] = el;
                    }
                    return result;
                }
            } else {//过滤模式
                for(i=0;el=lastResult[i++];){
                    if(reg.test(el.className || el.getAttribute("class")) ^ dom.lib.isNot)
                        result[ri++] = el;
                }
                return result;
            }
        }
    
        var queryDescendant = function(className,lastResult,tools){//后代选择器
            var result = [],ri = 0, isAll = !className,//如果为空字符串或undefined
            uniqResult = {}, i = 0 ,n = lastResult.length, j ,jn ,
            nodes, node,el, reg, uid;
            if(!isAll){
                reg =  new RegExp('(?:^|[ \\t\\r\\n\\f])' + className + '(?:$|[ \\t\\r\\n\\f])');
            }
            lastResult = lastResult.sort( dom.lib.pageOrder );
            //className二级查找模式,利用原生的getElementsByClassName实现高速化
            if(!isAll && tools.byClass){
                while(i < n){
                    nodes = lastResult[i++].getElementsByClassName(className);
                    j = 0;
                    jn = nodes.length;
                    while(j < jn){
                        node = nodes[j++];
                        uid = tools.uuid(node)
                        if(uniqResult[uid] !== node){
                            result[ri++] = uniqResult[uid] = node;
                        }
                    }
                }
            }else{
                while(i < n){
                    el = lastResult[i++];
                    if(uniqResult[tools.uuid(el)] !== el){
                        nodes = el.all || el.getElementsByTagName("*");
                        j = 0;
                        jn = nodes.length;
                        //className二级查找模式
                        while(j < jn){
                            node = nodes[j++];
                            if(uniqResult[tools.uuid(node)] === node) break;
                            if(node.nodeType === 1 && (isAll || reg.test(node.className || node.getAttribute("class")))){
                                uid = tools.uuid(node);
                                if(uniqResult[uid] === node){
                                    break;
                                }else{
                                    result[ri++] = uniqResult[uid] = node;
                                }
                            }
                        }
                    }
                }
            }
            return result;
        };
    
        var queryChild  = function (nodeName,lastResult,tools) {//亲子选择器
            var isAll = nodeName === "*",result = [],ri = 0,
            n = lastResult.length,i = 0 ,nodes ,node,j , jn,
            prop = tools.children ? "children" : "childNodes";
            while(i < n){
                nodes = lastResult[i++][prop];
                j = 0;
                jn = nodes.length;
                while(j < jn){
                    node = nodes[j++];
                    if( ( tools.children || node.nodeType === 1) &&(isAll || nodeName === node.nodeName))
                        result[ri++] = node;
                }
            }
            return result;
        };
    
        var queryGeneral = function (nodeName,lastResult,tools) {//兄长选择器
            var isAll = nodeName === "*",result = [],ri = 0,
            n = lastResult.length,i = 0 ,uniqResult = {}, uid, node,
            prop = tools.element ? "nextElementSibling" :"nextSibling"
            while(i < n){
                node = lastResult[i++];
                if(uniqResult[tools.uuid(node)] !== node){
                    for(node = node[prop];node;node = node[prop]){
                        if(uniqResult[node.uuid] === node) break;
                        if(( tools.element || node.nodeType === 1) && (isAll || nodeName === node.nodeName)){
                            uid = tools.uuid(node)
                            if(uniqResult[uid]){
                                break;
                            }else{
                                result[ri++] = uniqResult[uid] = node;
                            }
                        }
                    }
                }
            }
            return result;
        };
    
        var queryAdjacent = function (nodeName,lastResult,tools) { //相邻选择器
            var isAll = nodeName === "*", result = [],ri = 0,
            n = lastResult.length,i = 0 ,node,
            prop = tools.element ? "nextElementSibling" :"nextSibling";
            while(i < n){
                node = lastResult[i++];
                for(node = node[prop];node;node = node[prop]){
                    if(tools.element || node.nodeType === 1){
                        if (isAll || nodeName === node.nodeName)
                            result[ri++] = node;
                        break;
                    }
                }
            }
            return result;
        };
    
        var queryAttribute = function (name,operator,value,lastResult, root) { //属性选择器
            if(lastResult.length === 0)
                lastResult = queryWildcard(root);
            var result = [],ri = 0,reg;
            switch (operator) {
                case '$=':reg =  new RegExp(   value + '$' );break ;
                case '~=':reg =  new RegExp(  '(?:^|[ \\t\\r\\n\\f])' + value + '(?:$|[ \\t\\r\\n\\f])');break;
                case '|=':reg =  new RegExp(  '(?:^|\\|)' + value + '(?:$|\\|)');break;
            }
    
            var el , i = 0 ,n = lastResult.length,attrib,flag
    
            while(i < n){
                el = lastResult[i++];
                attrib = dom.attr(el, name);//取得元素的实际属性值
                flag = (attrib != null) && (attrib !== "");
                if(flag && operator)
                    switch (operator) {
                        case '=':  flag =  attrib === value ;break ;
                        case '!=': flag =  attrib !== value ;break ;
                        case '^=': flag =  attrib.indexOf(value) === 0 ;break ;
                        case '*=': flag =  attrib.indexOf(value) !== -1 ;break ;
                        default :  flag =  reg.test(attrib);break;
                    }
                if (!!flag  ^ dom.lib.isNot)
                    result[ri++] = el;
            }
            return result;
        }
    
        var queryPseudo = function (type, exp, lastResult,tools){//伪类选择器
            var position = _position
            if(lastResult.length === 0 )
                lastResult = queryWildcard(tools.context);
            var filter = filters[type], i = 0, n = lastResult.length, result = [],ri = 0, el;
            if(position[type]){//处理位置伪类
                //如果exp为空白则将集合的最大索引值传进去,否则将exp转换为数字
                exp = (exp === ""|| exp === void 0) ? n - 1 : ~~exp;
                while(i < n){
                    el = lastResult[i];
                    if(filter(i++, exp) ^ dom.lib.isNot)
                        result[ri++] = el;
                }
                return result;
            }
            if((typeof filter === "object") && filter.curry){
                var p = parseNth(exp);
                return filter.curry(lastResult, tools, p.a, p.b);
            }
            //处理target root checked disabled empty enabled lang 等伪类
            while(i < n){
                el = lastResult[i++];
                if(filter(el, exp, tools.context) ^ dom.lib.isNot)
                    result[ri++] = el;
            }
            return result;
        };
    
        //适配器,根据选择器的类型调用相应的函数去处理
        var dispatcher_ = {
            wildcard:function(array, nodes, tools) {    //通配符选择器
                return dom.lib.isNot ? [] :queryWildcard(tools.context);
            },
            tag : function(array, nodes, tools){ //标签选择器
                var nodeName = tools.xml ? array[0] :array[0].toUpperCase();
                return queryTag(nodeName , nodes, tools);
            },
            id : function(array, nodes, tools){               //ID选择器
                var id = array[1];
                return dom.lib.isNot ? queryAttribute("id","=",id, nodes ,tools.context)
                :dom.queryId(id, tools.context);
            },
            "class":function(array, nodes, tools){     //类选择器
                var className = array[1];
                return dom.lib.isNot ? queryAttribute("class","~=",className,nodes, tools.context):
                queryClass(className, nodes, tools);
            },
            descendant:function(array, nodes, tools){ //后代选择器(第一个参数为className)
                return queryDescendant(array[2], nodes, tools);
            },
            child:function(array, nodes,tools){       //亲子选择器(第一个参数为nodeName)
                var nodeName = array[2] || "*"
                nodeName = tools.xml ? nodeName :nodeName.toUpperCase();
                return queryChild(nodeName,nodes,tools);
            },
            general:function(array, nodes,tools){    //兄长选择器(第一个参数为nodeName)
                var nodeName = array[2] || "*"
                nodeName = tools.xml ? nodeName :nodeName.toUpperCase();
                return queryGeneral(nodeName,nodes,tools);
            },
            adjacent:function(array, nodes,tools){   //相邻选择器(第一个参数为nodeName)
                var nodeName = array[2] || "*"
                nodeName = tools.xml ? nodeName :nodeName.toUpperCase();
                return queryAdjacent(nodeName,nodes,tools)
            },
            attribute:function(array, nodes, tools){ //属性选择器
                return queryAttribute(array[1], array[2], array[4], nodes, tools.context);
            },
            pseudo:function(array, nodes,tools){      //伪类选择器
                return queryPseudo(array[1], array[3], nodes, tools);
            }
        }
        var isRelationAndTag_ = dom.oneObject(String("adjacent general child descendant tag").match(/\w+/g));
        var removeBlank_ = /\s*([>,\+\~=])\s*(?=(?:(?:[^"']*"[^"']*){2}|(?:[^"']*'[^"']*){2})*[^"']*$)/g;
    
        dom.query = function (selectors, context, lastResult) {
            var result = [],
            types = types_,//引用外围变量
            regexes = regexes_,//引用外围变量
            dispatcher = dispatcher_,//引用外围变量
            removeBlank = removeBlank_,
            root = context.documentElement,
            //若关系选择器与tag选择器跟着ID选择器,则可以直接kill掉前面的
            isRelationAndTag = isRelationAndTag_,
            xml = dom.isXML(context),
            tools = {//用于装载当前文档的各种判定
                xml : xml,
                children : "children" in root,
                context : context,
                //http://www.w3.org/TR/ElementTraversal/
                element : "nextElementSibling" in root,
                byClass : "getElementsByClassName" in root,
                uuid: xml ? getUIDXML : getUIDHTML
            };
            selectors = selectors.replace(removeBlank, function ($1, $2) {
                return $2;
            });
            selectors = selectors.replace(/^\s+|\s+$/g, '');
            if("querySelectorAll" in context){
                try{
                    var els = context.querySelectorAll(selectors);
    
                    if(dom.env.sliceNodes){
                        return Array.prototype.slice.call(els);
                    }else{
                        return dom.filter(els,function(el){
                            return el.nodeType === 1
                        });
                    }
    
                }catch(e){  }
            }
    
            while (selectors.length) {
                var type = types[selectors.charAt(0)] || "tag",
                regex = regexes[type],
                array = selectors.match(regex),//使用match才有rightContext,exec没有
                segment = RegExp.lastMatch;
                selectors = RegExp.rightContext;
                //后代选择器跟紧标签选择器的情形进行优化,如p span或#id span 或.class span
                //属于高级查找 var els = el.getElementsByTagName(tag)
                if(lastResult.length && type === "descendant"){
                    if(/[a-z0-9A-Z_]/.test(selectors.charAt(0))){//处理div div的情形
                        dom.lib.quickTag = true;
                        continue;
                    }
                    if(selectors.charAt(0) === "*"){//处理div *的情况
                        selectors = selectors.slice(1)
                    }
                }
                //如果是并联选择器,那么就把上次的结果集放进最终结果集中
                if(type === "combine") {
                    result = result.concat(lastResult);
                    lastResult = [];
                    continue;
                } else if(isRelationAndTag[type] && selectors.charAt(0) === "#"){
                    continue;
                }else if(segment.slice(0,4) === ":not"){
                    var add = segment.match(regexes.pseudo)[3] || "";
                    selectors = add + ":yes()"+ selectors ;//自定义一个伪类,标明反选选择器的结束
                    dom.lib.isNot = true;                  //使用反选选择器,反选选择器的括号里可以含有以下选择器
                    continue;                              //id,class,attribute,pseudo(not除外)
                }else if(segment.slice(0,4) === ":yes"){
                    dom.lib.isNot = false;
                    continue;
                }
                lastResult = dispatcher[type](array, lastResult, tools );
                //如果结果集的长度为零,则中止循环
                if (lastResult === undefined || lastResult.length === 0) {
                    break;
                }
            }
            //返回最终结果
            return result.concat(lastResult);
        }
    })(window[escape(document.URL.split("#")[0])],this);
    
    /*dom Framework version 1.0 Copyright 2010 Dual licensed under the MIT or GPL Version 2 licenses. author: <ruby> <rb>司徒正美<rp>(zhongqincheng)</rp></rb><rt>しとぅなさみ</rt></ruby> http://www.cnblogs.com/rubylouvre/ */ //========================================= // 选择器模块 //========================================== ;;;(function(dom,window,undefined){ dom.provide("query"); dom.lib.quickTag = false; dom.lib.isNot = false; dom.lib.pageOrder = ("sourceIndex" in document.documentElement) ? function (a, b) { return (a.sourceIndex - b.sourceIndex); }:function (a, b) { return (3 - (a.compareDocumentPosition(b) & 6)); }; //用于获取选择器的类型 var types_ = { "#":"id", //ID选择器 ".":"class", //类选择器 /*"tag"; //标签选择器*/ "[":"attribute", //属性选择器 " ":"descendant",//关系选择器(后代选择器) ">":"child", //关系选择器(亲子选择器) "+":"adjacent", //关系选择器(相邻选择器) "~":"general", //关系选择器(兄长选择器) ":":"pseudo", //伪类选择器 ",":"combine", //联合选择器 "*":"wildcard" //通配符选择器 } //用于移除相应的选择器 var regexes_ = { id: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, //ID选择器 tag: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, //标签选择器 attribute: /\[((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)(['"]*)(.*?)\3|)\]/, //属性选择器 "class": /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,//类选择器 pseudo: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/, //伪类选择器 combine: /,/, //联合选择器 child:/^(\>)\s*(\w*|\*)/, //亲子选择器 adjacent:/^(\+)\s*(\w*|\*)/, //相邻选择器 general:/^(\~)\s*(\w*|\*)/, //兄长选择器 descendant: /\s+(\.((?:[\w\u00c0-\uFFFF_-]|\\.)+))?/, //后代选择器 wildcard :/\*/ //通配符选择器 }; var queryPseudoHasExp = function(start_,next_,noCheck_){ return { curry :function(lastResult,a ,b){ //将外围变量变成本地变量 var start = start_,next = next_, isAll = noCheck_, result = [],ri = 0, uniqResult = {}, i = 0, n = lastResult.length, el, uid, find; while (i < n) { el = lastResult[i++]; uid = el.uuid || (el.uuid = "dom-"+ dom.uuid++), find = uniqResult[uid]; if (find === void 0) { for (var c = 0, node = el.parentNode[start], nodeName = el.nodeName;node; node = node[next]) if (node.nodeType === 1 && (isAll || nodeName === node.nodeName)) { ++c; uniqResult[node.uuid || (node.uuid = "dom-"+ dom.uuid++)] = a === 0 ? c === b : (c - b) % a === 0 && (c - b) / a >= 0; } find = uniqResult[uid]; } if (find ^ dom.lib.isNot) result[ri++] = el; } return result; } } } var queryPseudoNoExp = function(_direction,_noCheck){ return { curry : function(lastResult){ var result = [],ri = 0,els = lastResult,direction = _direction,isAll = _noCheck; for (var i = 0, el; el = els[i]; i++) { var tagName = isAll || el.nodeName, find = null if (find === null && direction <= 0){ for (var node = el.previousSibling; node; node = node.previousSibling) if (node.nodeType === 1 && (isAll || node.nodeName === tagName)) { find = false; break; } } if (find === null && direction >= 0) for (var node = el.nextSibling; node; node = node.nextSibling) if (node.nodeType === 1 && (isAll || node.nodeName === tagName)) { find = false; break; } if (find === null)//如果本身就是first-child或last-child find = true; if (find ^ dom.lib.isNot)//参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。 result[ri++] = el; } return result; } } } var filters = { //伪类选择器的过滤器 enabled: function(el){//标准 return el.disabled === false && el.type !== "hidden"; }, disabled: function(el){//标准 return el.disabled === true; }, checked: function(el){//标准 return el.checked === true; }, indeterminate:function(el){//标准 return el.indeterminate = true && el.type === "checkbox" }, selected: function(el){ el.parentNode.selectedIndex; return el.selected === true; }, empty: function (el) {//标准 return !el.firstChild; }, lang: function (el, value) {//标准 var reg = new RegExp("^" + value, "i") while (el && !el.getAttribute("lang")) el = el.parentNode; return !!(el && reg.test(el.getAttribute("lang"))); }, header: function(el){ return /h\d/i.test( el.nodeName ); }, button: function(el){ return "button" === el.type || el.nodeName === "BUTTON"; }, input: function(el){ return /input|select|textarea|button/i.test(el.nodeName); }, hidden : function( el ) { dom.require("node"); return el.type === "hidden" || dom.getStyle(el,"display") === "none" }, visible : function( el ) { dom.require("node"); return el.type !== "hidden" && dom.getStyle(el,"display") !== "none" }, link:function(el){ return el.nodeName.toLowerCase() === "a"; }, root:function(el){//标准 return el === (el.ownerDocument || el.document).documentElement; }, target:function(el,_,root){//标准 var id = root.location.hash.slice(1); return (el.id || el.name) === id; }, parent : function( el ) { return !!el.firstChild; }, contains: function(el, exp) { return (el.textContent||el.innerText||'').indexOf(exp) !== -1 }, "first-child": queryPseudoNoExp(-1, true),//标准 "last-child": queryPseudoNoExp( 1, true),//标准 "only-child": queryPseudoNoExp( 0, true),//标准 "first-of-type": queryPseudoNoExp(-1, false),//标准 "last-of-type": queryPseudoNoExp( 1, false),//标准 "only-of-type": queryPseudoNoExp( 0 ,false),//标准 "nth-child": queryPseudoHasExp("firstChild", "nextSibling", true),//标准 "nth-last-child": queryPseudoHasExp("lastChild", "previousSibling", true),//标准 "nth-of-type": queryPseudoHasExp("firstChild", "nextSibling", false),//标准 "nth-last-of-type": queryPseudoHasExp("lastChild", "previousSibling", false),//标准 //与位置相关的过滤器 first: function(index){ return index === 0; }, last: function(index, num){ return index === num; }, even: function(index){ return index % 2 === 0; }, odd: function(index){ return index % 2 === 1; }, lt: function(index, num){ return index < num; }, gt: function(index, num){ return index > num; }, eq: function(index, num){ return index === num; } }; dom.each(String("text radio checkbox file password submit image reset").match(/\w+/g), function(name){ filters[name] = function(el){ return el.type === name } }); var parseNth = function (exp) { var match = /(-?)(\d*)n([-+]?\d*)/.exec(exp === "even" && "2n" || exp === "odd" && "2n+1" || !/\D/.test(exp) && "0n+" + exp || exp); return { a: (match[1] + (match[2] || 1)) - 0, b: match[3] - 0 }; }; var position_ = dom.oneObject(String("eq gt lt first last even odd").match(/\w+/g)); //http://www.cnblogs.com/rubylouvre/archive/2009/11/25/1610044.html dom.queryId = function (id, context) { var el = (context || document).getElementById(id); return el && [el] || [] }; if(dom.env.mixupsName){ //如果浏览器的getElementById不能区分name与id dom.queryId = function(id,root){ root = root || document; var el = root.getElementById(id); if (el && el.attributes['id'].value === id) { return [el] } else { var all = root.all[id]; for(var i=0;el=all[i++];){ if(el.attributes['id'].value === id) return [el] } return [] } } } var queryWildcard = function (root) {//获得页面上或者某个元素节点下的所有元素 var all = root.all || root.getElementsByTagName("*"),result; if(dom.ie){ result = dom.filter(all,function(el){ return el.nodeType === 1 }); if(dom.env.traverseAllElements) dom.merge(result,(root.getElementsByTagName("param") || [])) return result; }else{ return dom.slice(all); } }; var queryTag = function(tagName, lastResult, root){ var result = [],ri = 0, n = lastResult.length, uniqResult = {},nodes; if(dom.lib.isNot){ var all = n ? lastResult :queryWildcard(root); return dom.filter(all,function(el){ return el.tagName.toLowerCase() !== tagName.toLowerCase() }); } if (n === 0) { return dom.filter(root.getElementsByTagName(tagName),function(){ return true; }); } else { var i = 0 ,j ,jn ,node ,uid ; if(dom.lib.quickTag ){ dom.lib.quickTag = false; while(i < n){ nodes = lastResult[i++].getElementsByTagName(tagName); j = 0; jn = nodes.length; while(j < jn){ node = nodes[j++]; uid = node.uuid || (node.uuid = "dom-"+dom.uuid++); if(uniqResult[uid] !== node){ result[ri++] = uniqResult[uid] = node; } } } return result; }else{ while(i < n){ node = lastResult[i++]; if(node.nodeName === tagName ) result[ri++] = node; } return result; } } } var queryClass = function (className, lastResult, root, flags) { var result = [],ri = 0,i = 0, n = lastResult.length, isNot = dom.lib.isNot, el, reg = new RegExp('(?:^|[ \\t\\r\\n\\f])' + className + '(?:$|[ \\t\\r\\n\\f])'); if (n === 0) {//查找模式 if (flags.byClass) { return Array.prototype.slice.call(root.getElementsByClassName(className)); } else { var els = root.all || root.getElementsByTagName("*"); for(i=0;el=els[i++];){ if(reg.test(el.className || el.getAttribute("class"))) result[ri++] = el; } return result; } } else {//过滤模式 for(i=0;el=lastResult[i++];){ if(reg.test(el.className || el.getAttribute("class")) ^ isNot) result[ri++] = el; } return result; } } var queryDescendant = function(className,lastResult,flags){//后代选择器 var result = [],ri = 0, isAll = !className,//如果为空字符串或undefined uniqResult = {}, i = 0 ,n = lastResult.length, j ,jn , nodes, node,el, reg, uid; if(!isAll){ reg = new RegExp('(?:^|[ \\t\\r\\n\\f])' + className + '(?:$|[ \\t\\r\\n\\f])'); } lastResult = lastResult.sort( dom.lib.pageOrder ); //className二级查找模式,利用原生的getElementsByClassName实现高速化 if(!isAll && flags.byClass){ while(i < n){ nodes = lastResult[i++].getElementsByClassName(className); j = 0; jn = nodes.length; while(j < jn){ node = nodes[j++]; uid = node.uuid || (node.uuid = "dom-"+dom.uuid++); if(uniqResult[uid] !== node){ result[ri++] = uniqResult[uid] = node; } } } }else{ while(i < n){ el = lastResult[i++]; if(uniqResult[el.uuid] !== el){ nodes = el.all || el.getElementsByTagName("*"); j = 0; jn = nodes.length; //className二级查找模式 while(j < jn){ node = nodes[j++]; if(uniqResult[node.uuid] === node) break; if(node.nodeType === 1 && (isAll || reg.test(node.className || node.getAttribute("class")))){ uid = node.uuid || (node.uuid = "dom-"+dom.uuid++); if(uniqResult[uid] === node){ break; }else{ result[ri++] = uniqResult[uid] = node; } } } } } } return result; }; var queryChild = function (nodeName,lastResult,flags) {//亲子选择器 var isAll = nodeName === "*",result = [],ri = 0, n = lastResult.length,i = 0 ,nodes ,node,j , jn, prop = flags.children ? "children" : "childNodes"; while(i < n){ nodes = lastResult[i++][prop]; j = 0; jn = nodes.length; while(j < jn){ node = nodes[j++]; if( ( flags.children || node.nodeType === 1) &&(isAll || nodeName === node.nodeName)) result[ri++] = node; } } return result; }; var queryGeneral = function (nodeName,lastResult,flags) {//兄长选择器 var isAll = nodeName === "*",result = [],ri = 0, n = lastResult.length,i = 0 ,uniqResult = {}, uid,node, prop = flags.element ? "nextElementSibling" :"nextSibling" while(i < n){ node = lastResult[i++]; if(uniqResult[node.uuid] !== node){ for(node = node[prop];node;node = node[prop]){ if(uniqResult[node.uuid] === node) break; if(( flags.element || node.nodeType === 1) && (isAll || nodeName === node.nodeName)){ uid = node.uuid || (node.uuid = "dom-"+dom.uuid++) if(uniqResult[uid]){ break; }else{ result[ri++] = uniqResult[uid] = node; } } } } } return result; }; var queryAdjacent = function (nodeName,lastResult,flags) { //相邻选择器 var isAll = nodeName === "*", result = [],ri = 0, n = lastResult.length,i = 0 ,node, prop = flags.element ? "nextElementSibling" :"nextSibling"; while(i < n){ node = lastResult[i++]; for(node = node[prop];node;node = node[prop]){ if(flags.element || node.nodeType === 1){ if (isAll || nodeName === node.nodeName) result[ri++] = node; break; } } } return result; }; var queryAttribute = function (name,operator,value,lastResult, root) { //属性选择器 if(lastResult.length === 0) lastResult = queryWildcard(root); var result = [],ri = 0,reg; switch (operator) { case '$=':reg = new RegExp( value + '$' );break ; case '~=':reg = new RegExp( '(?:^|[ \\t\\r\\n\\f])' + value + '(?:$|[ \\t\\r\\n\\f])');break; case '|=':reg = new RegExp( '(?:^|\\|)' + value + '(?:$|\\|)');break; } var el , i = 0 ,n = lastResult.length,attrib,flag while(i < n){ el = lastResult[i++]; attrib = dom.attr(el, name);//取得元素的实际属性值 flag = (attrib != null) && (attrib !== ""); if(flag && operator) switch (operator) { case '=': flag = attrib === value ;break ; case '!=': flag = attrib !== value ;break ; case '^=': flag = attrib.indexOf(value) === 0 ;break ; case '*=': flag = attrib.indexOf(value) !== -1 ;break ; default : flag = reg.test(attrib);break; } if (!!flag ^ dom.lib.isNot) result[ri++] = el; } return result; } var queryPseudo = function (type, exp, lastResult,root){//伪类选择器 var position = position_ if(lastResult.length === 0 ) lastResult = queryWildcard(root); var filter = filters[type], i = 0, n = lastResult.length, result = [],ri = 0, el; if(position[type]){//处理位置伪类 //如果exp为空白则将集合的最大索引值传进去,否则将exp转换为数字 exp = (exp === ""|| exp === void 0) ? n - 1 : ~~exp; while(i < n){ el = lastResult[i]; if(filter(i++, exp) ^ dom.lib.isNot) result[ri++] = el; } return result; } if((typeof filter === "object") && filter.curry){ return filter.curry(lastResult,parseNth(exp).a,parseNth(exp).b); } //处理target root checked disabled empty enabled lang 等伪类 while(i < n){ el = lastResult[i++]; if(filter(el, exp, root) ^ dom.lib.isNot) result[ri++] = el; } return result; }; //适配器,根据选择器的类型调用相应的函数去处理 var dispatcher_ = { wildcard:function(array,nodes,root) { //通配符选择器 return dom.lib.isNot ? [] :queryWildcard(root); }, tag : function(array, nodes, root, flags){ //标签选择器 var nodeName = flags.xml ? array[0] :array[0].toUpperCase(); return queryTag(nodeName , nodes, root); }, id : function(array, nodes, context){ //ID选择器 var id = array[1]; return dom.lib.isNot ? queryAttribute("id","=",id,nodes ,context) :dom.queryId(id, context); }, "class":function(array, nodes, root,flags){ //类选择器 var className = array[1]; return dom.lib.isNot ? queryAttribute("class","~=",className,nodes, root): queryClass(className, nodes, root, flags); }, descendant:function(array, nodes, root, flags){ //后代选择器(第一个参数为className) var className = array[2]; return queryDescendant(className, nodes, flags); }, child:function(array, nodes,root,flags){ //亲子选择器(第一个参数为nodeName) var nodeName = array[2] || "*" nodeName = flags.xml ? nodeName :nodeName.toUpperCase(); return queryChild(nodeName,nodes,flags); }, general:function(array, nodes,root,flags){ //兄长选择器(第一个参数为nodeName) var nodeName = array[2] || "*" nodeName = flags.xml ? nodeName :nodeName.toUpperCase(); return queryGeneral(nodeName,nodes,flags); }, adjacent:function(array, nodes,root,flags){ //相邻选择器(第一个参数为nodeName) var nodeName = array[2] || "*" nodeName = flags.xml ? nodeName :nodeName.toUpperCase(); return queryAdjacent(nodeName,nodes,flags) }, attribute:function(array, nodes,root){ //属性选择器 return queryAttribute(array[1],array[2], array[4],nodes, root); }, pseudo:function(array, nodes,root){ //伪类选择器 return queryPseudo(array[1], array[3], nodes,root); } } var isRelationAndTag_ = dom.oneObject(String("adjacent general child descendant tag").match(/\w+/g)); var removeBlank_ = /\s*([>,\+\~=])\s*(?=(?:(?:[^"']*"[^"']*){2}|(?:[^"']*'[^"']*){2})*[^"']*$)/g; dom.query = function (selectors, context, lastResult) { var result = [], types = types_,//引用外围变量 regexes = regexes_,//引用外围变量 dispatcher = dispatcher_,//引用外围变量 removeBlank = removeBlank_, root = context.documentElement, //若关系选择器与tag选择器跟着ID选择器,则可以直接kill掉前面的 isRelationAndTag = isRelationAndTag_, flags = {//用于装载当前文档的各种判定 xml : dom.isXML(context), children : "children" in root, //http://www.w3.org/TR/ElementTraversal/ element : "nextElementSibling" in root, byClass : "getElementsByClassName" in root }; selectors = selectors.replace(removeBlank, function ($1, $2) { return $2; }); selectors = selectors.replace(/^\s+|\s+$/g, ''); if("querySelectorAll" in context){ try{ var els = context.querySelectorAll(selectors); if(dom.env.sliceNodes){ return Array.prototype.slice.call(els); }else{ return dom.filter(els,function(el){ return el.nodeType === 1 }); } }catch(e){ } } while (selectors.length) { var type = types[selectors.charAt(0)] || "tag", regex = regexes[type], array = selectors.match(regex),//使用match才有rightContext,exec没有 segment = RegExp.lastMatch; selectors = RegExp.rightContext; //后代选择器跟紧标签选择器的情形进行优化,如p span或#id span 或.class span //属于高级查找 var els = el.getElementsByTagName(tag) if(lastResult.length && type === "descendant" && /[a-z0-9A-Z_]/.test(selectors.charAt(0))){ dom.lib.quickTag = true; continue; } //如果是并联选择器,那么就把上次的结果集放进最终结果集中 if(type === "combine") { result = result.concat(lastResult); lastResult = []; continue; } else if(isRelationAndTag[type] && selectors.charAt(0) === "#"){ continue; }else if(segment.slice(0,4) === ":not"){ var add = segment.match(regexes.pseudo)[3] || ""; selectors = add + ":yes()"+ selectors ;//自定义一个伪类,标明反选选择器的结束 dom.lib.isNot = true; //使用反选选择器,反选选择器的括号里可以含有以下选择器 continue; //id,class,attribute,pseudo(not除外) }else if(segment.slice(0,4) === ":yes"){ dom.lib.isNot = false; continue; } lastResult = dispatcher[type](array, lastResult, context, flags ); //如果结果集的长度为零,则中止循环 if (lastResult === undefined || lastResult.length === 0) { break; } } //返回最终结果 return result.concat(lastResult); } })(window[escape(document.URL.split("#")[0])],this);

    文档下载地址

    下载回来后对着文件点右键-->属性-->解除锁定。

    如果大家对上述方法有什么更好的实现,请不吝赐救!

  • 相关阅读:
    安装SQL sever2008时显示重新启动计算机规则失败,应该怎么解决?
    C#获取当前日期时间(转)
    使用JQUERY实现页面局部刷新
    Metal渲染:实现画面比例功能
    Metal渲染:实现旋转/翻转功能
    依赖注入浅析
    iOS 消息推送实现 APNS
    使用#pragma阻止一些warnings
    github 多帐户使用
    Swift 实现Bitmask Option(Enum)
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1765914.html
Copyright © 2011-2022 走看看