繁体   English   中英

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

[英]jquery: Paste a set of elements over another set of elements / merging elements

我有2套元素:

<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>        

我想将container1粘贴到container2上,以便覆盖任何替换,并且将每个容器的任何唯一内容放在一起并放在一起。

结果应该是:

<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>        

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

提前致谢。

由于您的问题被标记为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"));

你可以在这里尝试一下 ,结果是:

<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"则它将选择要覆盖的类。

这不是最有效的路线,因为你每次迭代都会在子项上启动选择器引擎,但除非你做了很多元素,否则应该很快。

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

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

这似乎做你想要的:

  <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>

这个答案:

  1. 完全符合你的要求。
  2. 如果div类container-result已经存在,则处理重复的mergings。
  3. 合并任意数量的容器div。
  4. 使用jQuery并且比其他一些解决方案更有效。

在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)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM