在IE中我們可以利用sourceIndex,標準瀏覽器我們可以用compareDocumentPosition,但對於舊一點的標準瀏覽器呢?XML呢?因此我們就需要根據一個節點的屬性確定它與另一個節點的關係了。
我的思路很簡單,如果它們相同,返回0(用於去重),如果它們的父節點相同,那麼根據nextSibling確定兩者的先後順序,否則就找到其最近公用祖先與其他兩個最接近這祖先的兩個父節點(人性點說,是伯父與父親),這時不就是與父節點相同的情況嗎?!根據nextSibling確定它們的順序,它們的順序就是它們的孩子的順序(因此有一個叫李剛的爹很重要,在這個世襲制的世界上!)不過,有時最近公用祖先就是比較雙方的某一個呢,那當然是它最近了。
剩下的問題就是求最近公用祖先的問題了。我的思路也很簡單,不一定高效,畢竟大學把數學都荒廢了。不斷向上取得它們的父節點,直到最頂的HTML元素,連同最初那個節點,組成兩個數組。然後每次取數組最後的元素進行比較,如果相同就去掉它們,因為相同的都是公用祖先,不相同就往上取其中一方就行了。
下面是測試頁面與源碼:
由於使用了window.console,因此建議在firefox,IE8,chrome下查看結果。
<!doctype html> <html> <head> <title>節點排序 </title> <script> window.onload = function(){ function shuffle(a) { var array = a.concat(); var i = array.length; while (i) { var j = Math.floor(Math.random()*i); var t = array[--i]; array[i] = array[j]; array[j] = t; } return array; } var log =function(s){ window.console && window.console.log(s) } var sliceNodes = function(arr){ var ret = [], i = arr.length; while (i) ret[--i] = arr[i]; return ret; } var sortNodes = function(a,b){ var p = "parentNode",ap = a[p],bp = b[p]; if(a === b){ return 0 }else if(ap === bp){//如果父節點相同 while(a = a.nextSibling){//比較這兩兄弟 if(a === b){ return -1 } } return 1 }else if(!ap){ return -1 }else if(!bp){ return 1 } var al = [], ap = a while(ap && ap.nodeType === 1){ al[al.length] = ap ap = ap[p] } var bl = [],bp = b; while(bp && bp.nodeType === 1){ bl[bl.length] = bp bp = bp[p] } ap = al.pop(); bp = bl.pop(); while(ap === bp){//去掉所有公用祖先 ap = al.pop(); bp = bl.pop(); } if(ap && bp){//比較伯父與父親 while(ap = ap.nextSibling){ if(ap === bp){ return -1 } } return 1 } //如果是最近公用祖先與某一方進行比較 return ap ? 1 : -1 } var els = document.getElementsByTagName("div") els = sliceNodes(els);//轉換成純數組 log(els); els = shuffle(els);//洗牌(模似用自訂的選取器取得的節點集合情況) log(els); els = els.sort(sortNodes) log(els) } </script> </head> <body> <form> <div id="aa1" > <div id="aa2">111</div> <div id="aa3">222<div>00</div></div> <div id="aa4">44<div id="aa5">111</div></div> </div> <div id="aa6">22</div> <div id="aa7"><p>Hello</p></div> <div id="aa8"> <div id="aa9">888</div> <div id="aa10">999</div> </div> </form> </body> </html>
[Ctrl+A 全選 注:如需引入外部Js需重新整理才能執行]