這個以前已經研究過了,但嫌速度不夠快,重新搞了一個。現在略略重申一下問題,比如有一個節點集合[a,b,c,d,e],其中,a是b的父節點, d是b的父節點,我要的結果是去掉這些存在內含項目關聯性的節點中的被包含者,換言之,最終得到[c,d,e]。
這裡可能用到contains函數:預先列出來吧。
//http://www.cnblogs.com/rubylouvre/archive/2009/10/14/1583523.html var contains = function(ancestor,node) { if (node.compareDocumentPosition) return (node.compareDocumentPosition(ancestor) & 8) === 8; if (ancestor.contains) return ancestor.contains(node) && ancestor !== node; while (node = node.parentNode) if (node == ancestor) return true; return false; }
如果得到不存在內含項目關聯性的祖先節點集合對後代選取器與萬用字元選取器的實現至關重要,因為它涉及去重與排序問題。以前我不懂這一點,一古腦地沖一去,得到所有後代再進行排序去重,慢死了。我新一代的選取器絕然不能走這老路了。
當然,像我這樣想的,我絕對不是第一位。如百度的Fox選取器就存在這麼一個函數:
/** * 得到一個樹集合中第一層級的節點* @method getFirstLevelNodes* @static* @param {HTMLElements|Array} 樹集合節點* @return {Array} 返回第一層的節點集合數組*/Fox.getFirstLevelNodes = function(nodes) {for (var i=1; i 但這個函數存在一個致命的缺陷,就是要求nodes為節點數組,而不是節點集合。要知道像節點集合轉換為純數組可不是什麼一蹴而成的事,可惡的IE的節點集合不能輕易用Array.prototype.slice.call就轉換掉,而且逐一放進空數組時,還要留意是否混入了注釋節點。另外,每次得到元素節點就進行轉換太不現實了。因此我的祖先擷取函數必須支援節點集合。下面是我新的函數:
// by 司徒正美 取得不存在內含項目關聯性的祖先節點集合// http://www.cnblogs.com/rubylouvre/archive/2010/12/29/1920358.html#var dom = { UID: 1, getAncestor: function (els) { var el, node, nodes = [], i = 0, ri = 0, uniqResult = {}; while (el = els[i++]) { node = el; do { pid = node.uniqueID || (node.uniqueID = dom.UID++); if (uniqResult[pid]) { break; } else if (node.nodeType === 9) { //如果能到達文檔對象 uniqResult[el.uniqueID] = nodes[ri++] = el; } }while( node = node.parentNode); } return nodes; }}<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>得到不存在內含項目關聯性的祖先節點集合 by 司徒正美</title><br /> <script type="text/javascript" charset="utf-8"><br /> window.onload = function(){<br />var arr = document.getElementsByTagName("div");<br />var dom = {<br /> UID: 1,<br /> getAncestor: function (els) {<br /> var el, node, nodes = [],<br /> i = 0,<br /> ri = 0,<br /> uniqResult = {};<br /> while (el = els[i++]) {<br /> node = el;<br /> do {<br /> pid = node.uniqueID || (node.uniqueID = dom.UID++);<br /> if (uniqResult[pid]) {<br /> break;<br /> } else if (node.nodeType === 9) { //如果能到達文檔對象<br /> uniqResult[el.uniqueID] = nodes[ri++] = el;<br /> }<br /> }while( node = node.parentNode);<br /> }<br /> return nodes;<br /> }<br />}<br /> var ancestor = dom.getAncestor(arr)<br /> for(var i=0,n=ancestor.length;i<n;i++){<br /> alert(ancestor[i].id)<br /> }</p><p> }</p><p> </script><br /> </head><br /> <body><br /> <div id="id1">一<div id="id2">二</div><div id="id3">二</div><div class="bbb">二</div></div></p><p> <div id="id4">一<div id="id5">二</div></div><br /> <div id="id6" title="aaa">一<div title="aaa">二</div></div><br /> <div id="id7"><br /> <div id="id8"><strong id="id9">Strong<div id="id10">二</div></strong></div><br /> </div><br /> </body></p><p></html><br />
運行代碼
相關文章:擷取祖先元素