0

I want to clone a div using it's id with many elements inside it which also has their own id that I want to change after cloning.

Consider this HTML structure:

<div id='wrapper1'>
  <p id='test1'>Hello</p>
  <p id='my-awesome-id1'></p>
</div>

I found this on SO but it only changes the id of the main element you cloned and not the children.

Is there a way I could do it so that I could update all of the 1 into 2 and so on?

Community
  • 1
  • 1
dokgu
  • 4,957
  • 3
  • 39
  • 77
  • I just answered almost similar question [Here](http://stackoverflow.com/a/36040947/1627271). See if it would help. – choz Mar 16 '16 at 16:19

2 Answers2

3

This would do it and create a clone like:

<div id="wrapper2">
  <p id="test2">Hello</p>
  <p id="my-awesome-id2"></p>
</div>

$('div').clone().filter(function() {
  $(this).prop('id', $(this).prop('id').replace('1', '2')).children().filter(function() {
    return $(this).prop('id', $(this).prop('id').replace('1', '2'))
  });
  return $(this)
}).appendTo('body')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='wrapper1'>
  <p id='test1'>Hello</p>
  <p id='my-awesome-id1'></p>
</div>
j08691
  • 204,283
  • 31
  • 260
  • 272
  • Forget what I mentioned above. Let's say according to my example `test1` is defined as `

    Hello

    `, how do I do the changing for both the `id` and the `data-num` attribute?
    – dokgu Mar 16 '16 at 16:42
  • I also just noticed that if an element inside `wrapper1` has no `id` in the first place, your solution would add that attribute but with no value. Would this be an issue or is it safe to leave it like that? – dokgu Mar 16 '16 at 16:48
  • To answer your first question you'd just check for a matching data attribute and do s similar replace on the data attribute instead of the ID, and as to your second question an empty attribute is fine, however you could also just add a check first before doing the replace. – j08691 Mar 16 '16 at 16:50
  • Should I put the check inside the first or the second `filter`? – dokgu Mar 16 '16 at 16:51
  • The second (inner) filter checks the children (`

    `) elements, so that one.

    – j08691 Mar 16 '16 at 16:56
  • Ok I managed to fix everything now. Thanks a lot! Your solution only works for direct children I believe. It doesn't work for grandchildren or descendants. – dokgu Mar 16 '16 at 17:04
  • 1
    That's correct. `children()` only looks at children. For deeper down the hierarchy you could use `find('*')`. – j08691 Mar 16 '16 at 17:06
  • Thanks a bunch! That helped quite a lot! – dokgu Mar 16 '16 at 17:08
0

You can use a function like this:

function changeIdNumberOnElementAndChildren(element, newIdNumber) {
    var $element = $(element),
        $elementChildren = $element.children(),
        oldId = $element.attr("id"),
        newId = (oldId) ? oldId.replace(/\d+$/, newIdNumber) : null;

    if (newId) {
        $element.attr("id", newId);
    }

    if ($elementChildren.length > 0) { // recursively call function on children
        $elementChildren.each(function(i, child) {
            changeIdNumberOnElementAndChildren(child, newIdNumber);
        });
    }
}

Then simply call it on a clone to change the ids:

$(function() {
    var clone = $("#wrapper1").clone();
    // below changes the ids so that they end in 559 rather than 1
    // (i.e. "wrapper559", "test559" and "my-awesome-id559")
    changeIdNumberOnElementAndChildren(clone, 559);
});
user162097
  • 1,250
  • 11
  • 21