原來選取器只支援一個上下文,並對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 另一種改進是,通過對元素節點的上下文添加一個類名,這樣尋找就可以一步到位。不足之處就是前前後後要對類進行操作。
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快捷得多了。