代码之家  ›  专栏  ›  技术社区  ›  Mark

jquery:将一组元素粘贴到另一组元素上/合并元素

  •  3
  • Mark  · 技术社区  · 15 年前

    <div class='container container1'>
        <div class='colors'>
            <div class='blue'></div>
            <div class='red'></div>
        </div>
        <div class='drinks'>
            <div class='soda'>coke</div>
            <div class='juice'></div>
        </div>
    </div>    
    
    <div class='container container2'>
        <div class='cars'>
            <div class='sedans'></div>
            <div class='vans'></div>
        </div>
        <div class='drinks'>
            <div class='soda'>mountain dew</div>
            <div class='coffee'></div>
        </div>
    </div>        
    

    结果应该是:

    <div class='container container-result'>
        <div class='colors'>
            <div class='blue'></div>
            <div class='red'></div>
        </div>
        <div class='cars'>
            <div class='sedans'></div>
            <div class='vans'></div>
        </div>
        <div class='drinks'>
            <div class='soda'>coke</div>
            <div class='juice'></div>
            <div class='coffee'></div>
        </div>
    </div>        
    

    元素可以具有任意层次/深度。最好的办法是什么?

    提前谢谢。

    4 回复  |  直到 15 年前
        1
  •  1
  •   Nick Craver    15 年前

    由于您的问题被标记为jQuery,因此使用该库可以得到一个略短的答案:

    function copy(from, to) {
        from.children().each(function() {
          var match = to.children("." + this.className.split(' ').join('.'));
            if(match.length) {
                if(match.children().length == 0) {
                    match.replaceWith(this);
                } else {
                    copy($(this), match);
                }
            } else {
                to.append(this);
            }
        }).end().remove();
        from.remove();
    }
    

    那你就这样称呼它:

    copy($(".container1"), $(".container2"));
    

    You can give it a try here

    <div class="container container2">
      <div class="cars">
        <div class="sedans"></div>
        <div class="vans"></div>
      </div>
      <div class="drinks">
        <div class="soda">coke</div>
        <div class="coffee"></div>
        <div class="juice"></div></div>
      <div class="colors">
        <div class="blue"></div>
        <div class="red"></div>
      </div>
    </div>
    

    注意类名仍然是 container2 copy()

    $(".container2").toggleClass("container2 container-result");
    

    匹配基于元素包含的所有类,因此如果元素 class="car blue" class="blue car" 它会选择覆盖那个。

    太多了

        2
  •  0
  •   Paul Dragoonis    15 年前

    关于独特的合并我不能帮助你,但如果你的应用程序碰巧是在PHP中,那么你可以使用PHP的 array_merge 函数在输出HTML之前合并它们。

    ReplaceWith 是一个很好的jquery函数来代替aka“粘贴”过来,它可能会帮你解决一半的问题。

        3
  •  0
  •   John Fisher    15 年前

    这似乎是你想要的:

      <div class='container container1'>
          <div class='colors'>
              <div class='blue'></div>
              <div class='red'></div>
          </div>
          <div class='drinks'>
              <div class='soda'>coke</div>
              <div class='juice'></div>
          </div>
      </div>    
    
      <div class='container container2'>
          <div class='cars'>
              <div class='sedans'></div>
              <div class='vans'></div>
          </div>
          <div class='drinks'>
              <div class='soda'>mountain dew</div>
              <div class='coffee'></div>
          </div>
      </div>        
    
      <div class='container container-result'>
      </div>
    
      <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js" type="text/javascript"></script>
      <script type="text/javascript">
    
        function getContainerArray(containers, level) {
          level = level || 0;
          var result = [];
          for (var i=0; i<containers.length; ++i) {
            var el = containers.eq(i);
            var obj = { "class": el.attr("class") };
            if (level == 0) {
              obj.items = getContainerArray(el.children("div"), 1);
            } else {
              obj.text = el.text();
            }
            result.push(obj);
          }
          return result;
        }
    
        function mergeContainers(containerArray) {
          var result = [];
    
          function indexOfClass(name) {
            for (var i = 0; i < result.length; ++i) {
              if (result[i]["class"] == name) {
                return i;
              }
            }
            return -1;
          }
    
          for (var i = 0; i < containerArray.length; ++i) {
            var obj = containerArray[i];
            var name = obj["class"];
            var index = indexOfClass(name);
            if (index < 0) {
              result.push(obj);
            } else if (obj.items != null) {
              result[index].items = mergeContainers(new Array().concat(result[index].items, obj.items));
            }
          }
    
          return result;
        }
    
        function getHtml(objArray) {
          var result = [];
          for (var i = 0; i < objArray.length; ++i) {
            var obj = objArray[i];
            result.push("<div class=\"", obj["class"], "\">");
            if (obj.text != null && obj.text != "") {
              result.push(obj.text);
            }
            if (obj.items != null) {
              result.push(getHtml(obj.items));
            }
            result.push("</div>");
          }
          return result.join("");
        }
    
        var html = getHtml(mergeContainers(getContainerArray($("div.container1>div,div.container2>div"))));
        $("div.container-result").append(html);
      </script>
    
        4
  •  0
  •   Brock Adams    15 年前

    答案是:

    1. 照你说的做。
    2. container-result
    3. 合并任意数量的容器div。

    See it in action at jsfiddle.net.

    /*--- Get all "container" divs but exclude any "container-result" divs.
    */
    var zContainers = $("div.container").not ("div.container-result");
    if (zContainers  &&  zContainers.length)
    {
        //--- Get or create the results div.
        var zResultDiv  = $("div.container-result");
        if (!zResultDiv  ||  !zResultDiv.length)
        {
            zResultDiv  = zContainers.parent ().append ("<div class='container container-result'></div>");
            zResultDiv  = $("div.container-result");
        }
    
        //--- Move the container's contents to the master container, preserving order.
        zContainers.each (function () {$(this).children ().appendTo (zResultDiv);} )
    
        //--- Kill the old container(s).
        zContainers.remove ();
    
        RecursivelyMergeDivsByClass (zResultDiv);
    }
    
    function RecursivelyMergeDivsByClass (jNode)
    {
        /*--- Get a list of the direct-child div's class names.
            Sort and winny out a list of duplicates.
        */
        var zDirectChildDivs    = jNode.find ("> div");
        var aClassList          = zDirectChildDivs.map (function () {return this.className;} ).get ();
        aClassList.sort ().unshift (0);
    
        for (var J = aClassList.length-1;  J > 0;  J--)
            if (aClassList[J] != aClassList[J-1])   aClassList.splice (J, 1); // Delete items without duplicates.
    
        aClassList.splice (0, 1);
    
        /*--- For any duplicates, copy the contents into the first instance, preserving order.
            For exact duplicate nodes, the first (oldest) version is kept and the remaining are discarded.
        */
        for (var J = aClassList.length-1;  J >= 0;  J--)
        {
            var zDupClasses     = zDirectChildDivs.filter ("." + aClassList[J]);
    
            var zFirstDiv       = zDupClasses.first ();
            zDupClasses         = zDupClasses.not (zFirstDiv);
    
            zDupClasses.each (function () {$(this).children ().appendTo (zFirstDiv);} )
            zDupClasses.remove ();
    
            RecursivelyMergeDivsByClass (zFirstDiv)
        }
    }