Jquery: Insert a set of elements over another set of elements / merge elements

I have 2 sets of elements:

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

I want to insert container1 on top of container2 so that any replacements are written with an inscription, and any uniqueness for each container is left alone and put together.

The result should be:

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

Elements can have any arbitrary hierarchy / depth. What is the best way to do this?

Thanks in advance.

+3
source share
4 answers

Since your question is tagged jQuery here is a little shorter using this library:

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();
}

Then you simply call it like this:

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

Here you can try here , the result:

<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", , .

, , , .

+1

, , PHP, php array_merge, HTML.

ReplaceWith - jquery aka "paste", .

0

, :

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

:

  • , .
  • Handles recurring merges if a div class container-resultalready exists.
  • Combines any number of div containers.
  • Uses jQuery and more efficiently than other solutions.

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 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 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)
    }
}
0
source

Source: https://habr.com/ru/post/1757501/


All Articles