获取祖先元素
在设计选择器时遇到的,当我们使用后代选择器,要从上一次的结果集中获取它们所有后代,可能存在重复元素。虽然排除重复元素是非常简单的事,但我们能不能从一开始就防范其生产重复元素呢?答案是肯定。
假设上一次的结果集有三个元素a,b,c,如果其中两个存在包含关系,即是说A的parentNode或祖先是B,那么一定会出现重复的子集。既然如此,一开始,我们把A去掉,就没问题了。
看下面网页:
<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>排除 重复元素 by 司徒正美</title>
</head>
<body id="id10">
<p id="id1">一<span id="id2">二</span><span id="id3">二</span><span class="bbb">二</span></p>
<p id="id4">一<span id="id5">二</span></p>
<p title="aaa">一<span title="aaa">二</span></p>
<div id="id6">
<p id="id7"><strong id="id8">Strong<span id="id9">二</span></strong></p>
</div>
</body>
</html>
我们从它里面选择几个元素组成数组,模拟为选择器上一次选取的结果。
window.onload = function(){
var $ = function(id){
return document.getElementById(id);
}
var a = $("id1");
var b = $("id2")
var c = $("id3")
var d = $("id4")
var e = $("id5")
var f = $("id6")
var g = $("id7")
var h = $("id8")
var arr = [a,b,c,d,e,f,g,h];
}
由于网页很简单,我们一眼就看得出,最终应该从中筛选出:a,d,f。
要实现这个目标,我们必须先对数组进行排序,让元素安排它们在页面上的位置从上到下,从左到右排序。这简单, 我们可以通过以下方法实现:
var sortOrder = function(){
if(!+"\v1"){
return function( a, b ) {
return a.sourceIndex - b.sourceIndex;
}
}else{
return function(a,b){
a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
}
}
}();
我们还需要检测它们是否存在包含关系:
var contains = function(a,b){
if(!+"\v1"){
return a === b ? false : a.contains(b);
}else{
return !!(a.compareDocumentPosition(b) & 16)
}
}
最后我们进行两两比较,把儿子与孙子都找出来,打上标记,没有标记的就是我们要找的祖先,那么从这些祖先获取的后代集合就一定没有重复元素了!
arr.sort(sortOrder);
var getAncestor = function(array){
for (var i = 0,n=array.length; i < n; i++) {
for (var j = n - 1; j > i; j--) {
var a = array[i],b=array[j];
if (contains(a,b)) {
b.no = 1;
}else if(contains(b,a)) {
a.no = 1
}
}
}
var result = [],ri= 0
for(var k=0;k<n;k++){
if(!array[k].no){
result[ri++] = array[k]
}
}
return result;
}
var ancestor= getAncestor(arr)
但是这样做有个致命的缺陷,就是只能筛选一次,下一次这个no私有属性将成为干扰因素,但移除私有属性费时费劲,因此建议使用uuid技术进行筛选。
arr.sort(sortOrder);
var uuid = 0
var getAncestor = function(array){
var remove = {},uid ;
for (var i = 0,n=array.length; i < n; i++) {
for (var j = n - 1; j > i; j--) { //比如一共有五个元素,那么每趟为
var a = array[i],b=array[j];
if (contains(a,b)) {
uid = b.uuid || (b.uuid = "dom-"+uuid++) ;
remove[uid] = 1;
}else if(contains(b,a)) {
uid = a.uuid || (a.uuid = "dom-"+uuid++);
remove[uid] = 1;
}
}
}
var result = [],ri= 0
for(var k=0;k<n;k++){
if(!remove[array[k].uuid]){
result[ri++] = array[k]
}
}
return result;
}
var ancestor = getAncestor(arr)
for(var i=0,n=ancestor.length;i<n;i++){
alert(ancestor[i].id)
}
机器瞎学/数据掩埋/模式混淆/人工智障/深度遗忘/神经掉线/计算机幻觉/专注单身二十五年
浙公网安备 33010602011771号