This method of "copying" HTML elements from one place to another is the result of a misunderstanding of what the browser does. Browsers do not store the HTML document in memory somewhere and repeatedly modify HTML based on commands from JavaScript.
When the browser first loads the page, it parses the HTML document and turns it into a DOM structure. This is the ratio of objects following the W3C standard (well, basically ...). Since then, the original HTML is completely redundant. The browser doesn't care what the original HTML structure was; his understanding of a web page is a DOM structure that was created from it. If your HTML markup is incorrect / invalid, it will be somehow fixed by the web browser; the DOM structure will not contain any invalid code.
In principle, HTML should be considered as a way to serialize the DOM structure, which must be transmitted over the Internet or stored in a local file.
Therefore, it should not be used to modify an existing web page. The DOM (Document Object Model) has a system for modifying page content. This is based on node relationships, not HTML serialization. Therefore, when you add li to ul , you have these two options (assuming ul is a list item):
// option 1: innerHTML ul.innerHTML += '<li>foobar</li>'; // option 2: DOM manipulation var li = document.createElement('li'); li.appendChild(document.createTextNode('foobar')); ul.appendChild(li);
Now the first option looks a lot simpler, but this only happens because the browser is very distracted by you: internally, the browser must convert the children to a string, then add some content, and then convert back to the DOM structure. The second option corresponds to the concept of the browser about what is happening.
A second important consideration is to consider the limitations of HTML. When you think of a web page, not everything that is relevant to an element can be serialized in HTML. For example, event handlers associated with x.onclick = function(); or x.addEventListener(...) will not be replicated to innerHTML , so they will not be copied. Thus, new elements in y will not have event listeners. This is probably not what you want.
So, the way around this is to work with your own DOM methods:
for (var i = 0; i < x.childNodes.length; i++) { y.appendChild(x.childNodes[i].cloneNode(true)); }
Reading the MDN documentation will probably help to understand this way:
Now the problem with this (as with option 2 in the example above) is that it is very verbose, much longer than the innerHTML option. This is when you value having a JavaScript library that does this for you. For example, in jQuery:
$('#y').html($('#x').clone(true, true).contents());
This is a much more explicit description of what you want. For example, with various performance benefits and maintaining event handlers, it also helps to understand what your code does. This is good for your soul as a JavaScript programmer and makes fancy bugs significantly less likely!