zoukankan      html  css  js  c++  java
  • 获取祖先元素

    在设计选择器时遇到的,当我们使用后代选择器,要从上一次的结果集中获取它们所有后代,可能存在重复元素。虽然排除重复元素是非常简单的事,但我们能不能从一开始就防范其生产重复元素呢?答案是肯定。

    假设上一次的结果集有三个元素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)
            }
    

  • 相关阅读:
    zTree 优秀的jquery树插件
    The underlying provider failed on open 问题解决
    HTML 5 <input> list 属性
    C#拖曳控件加载,bll报错问题
    把VS2010的智能代码提示和注解从英文变成中文
    progressBar的使用
    C++内存读写例子
    bash 管理小脚本
    KVM虚拟机配置笔记
    Ettercap 实施中间人攻击
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1654965.html
Copyright © 2011-2022 走看看