Ruby's Louvre

每天学习一点点算法

导航

querySelector用法改进

原来选择器只支持一个上下文,并对IE8的BUG进行了规避

     if (!flag_xml && doc.querySelectorAll) {//FF,opera,chrome,safari的XML文档也实现了querySelectorAll接口,但不能用
                var query = expr;//IE的getElementsByTagName,querySelectorAll对OBJECT元素的孩子的查找都存在问题
                if( doc.documentMode === 8 && context.nodeType === 1 && context.nodeName.toLowerCase() !== "object"){
                    var id = context.getAttribute( "id" ),uid = context.uniqueID//IE8在上下文为元素节时,搜索结果包含自己
                    if ( !id ) {
                        context.setAttribute( "id", uid );
                    }
                    try {
                        return pushResult(context.querySelectorAll( "#" + uid + " " + query ),result,flag_multi);
                    } catch(e) {
                    } finally {
                        if ( id == context.uniqueID ) {
                            context.removeAttribute( "id" );
                        }
                    }
                }else{
                    if(/\!\=/.test(query))//手动支持 E[Attr!=Val]
                        query = query.replace(/\[\s*(\w+)\s*!=\s*((['"]*).*?\3)\s*\]/g,":not([$1=$2])");
                    try {
                        return pushResult( context.querySelectorAll(query) ,result,flag_multi);
                    } catch(e) {}
                }
            }

改进如下,现在只需规避IE的OBJECT bug。

            if (!flag_xml && doc.querySelectorAll) {//http://www.w3.org/TR/selectors/
                node = context;//使用替身,以便在多上下文实现不重排查找
                var useContains = false;
                if(contexts.length > 2 || doc.documentMode === 8 && context.nodeType === 1){
                    node = doc;
                    useContains = true;
                }
                if(doc.documentMode !== 8  ||  node.nodeName.toLowerCase() !== "object"){
                    try{
                        nodes = pushResult( node.querySelectorAll(expr) ,result,flag_multi);
                        var ret = []
                        if(useContains && nodes.length){
                            var cn = contexts.length;
                            for(i = 0, ri = 0; i < nodes.length; i++){
                                inner:
                                for(var c = 0; c < cn; c++){
                                    if(dom.contains(contexts[c], nodes[i])){
                                        ret.push(nodes[i])
                                        break inner;
                                    }
                                }
                            }
                            return ret;
                        }
                        return result;
                    }catch(e){}
                }
            }

另一种改进是,通过对元素节点的上下文添加一个类名,这样查找就可以一步到位。不足之处就是前前后后要对类进行操作。

            if (!flag_xml && doc.querySelectorAll) {
                var query = expr;
                if(contexts.length > 2 || doc.documentMode == 8  && context.nodeType == 1  ){
                    if(contexts.length > 2 )
                        context = doc;
                    query = ".fix_icarus_sqa "+query;//IE8也要使用类名确保查找范围
                    for(i = 0; node = contexts[i++];){
                        if(node.nodeType === 1){
                            node.className = "fix_icarus_sqa " + node.className;
                        }
                    }
                }
                if(doc.documentMode !== 8  || context.nodeName.toLowerCase() !== "object"){
                    try{
                        result = pushResult( context.querySelectorAll(query) ,result,flag_multi);
                        if(query.indexOf(".fix_icarus_sqa") === 0 ){//如果为上下文添加了类名,就要去类名
                            for(i = 0; node = contexts[i++];){
                                if(node.nodeType === 1){
                                    node.className =  node.className.replace(" fix_icarus_sqa","");
                                }
                            }
                        }
                        return result;
                    }catch(e){}
                }
            }

但显然对类进行操作对调用dom.contains快捷得多了。

posted on 2011-11-08 03:35  司徒正美  阅读(2684)  评论(1编辑  收藏  举报