Cosplay photograph of three clones of Alice, from the Resident Evil series

If you’ve read previous entries in this series or are familiar with JS, you’ll know that it is pretty straightforward to remove an element from a page with JavaScript. Given this HTML:

<h1>IF THE SUSPENSE DOESN’T KILL YOU
<span>SOMETHING ELSE WILL</span></h1>
<p id="open"><span>CLOSE ON GLASS VIALS</span> being lifted from a large medical refrigerator. Gloved hands slip them into a foam lined carry case. The vials are delicate. Filled with a cool blue liquid. The hands move quickly. Urgently.</p>
<p>Sleek, super hi—tech. The blinds are closed. Can’t tell if it’s day or night.</p>
<p>Typists type. Assistants assist.</p>
<p id="bees">Busy worker bees.</p>

In almost all modern browsers we can identify and remove the “bees” paragraph with:

var bees = document.getElementById("bees");
bees.remove();

We could then move the “bees” paragraph to become the very first element in the page with the following:

document.body.insertBefore(bees, document.body.firstElementChild);

The DOM of the page would now be:

<p id="bees">Busy worker bees.</p>
<h1>IF THE SUSPENSE DOESN’T KILL YOU
<span>SOMETHING ELSE WILL</span></h1>
<p id="open"><span>CLOSE ON GLASS VIALS</span> being lifted from a large medical refrigerator. Gloved hands slip them into a foam lined carry case. The vials are delicate. Filled with a cool blue liquid. The hands move quickly. Urgently.</p>
<p>Sleek, super hi—tech. The blinds are closed. Can’t tell if it’s day or night.</p>
<p>Typists type. Assistants assist.</p>

This is the equivalent to “cut and paste” in JavaScript. But what if we identified “bees”, only to immediately place it as the first element? That should be the equivalent of “copy and paste” in JavaScript, right?

var bees = document.getElementById("bees");
document.body.insertBefore(bees, document.body.firstElementChild);

The answer is “nope”: this gives us the same result as before, moving the element from the end of the document to the beginning. bees is a live reference to an element, and what we do to it is reflected directly in the DOM.

You might think that we could create a new variable based on bees, and substitute that:

var bees = document.getElementById("bees");
var swarm = bees;
document.body.insertBefore(swarm, document.body.firstElementChild);

But that doesn’t work either: JavaScript considers bees exactly equivalent to swarm, and as referring to the same object, so the result is the same as before: the element is moved from point A to point B. What we need is a clone of the original object.

var bees = document.getElementById("bees");
var swarm = bees.cloneNode(true);
document.body.insertBefore(swarm, document.body.firstElementChild);

Now the result is what we expect: a copy of bees at the start and end of the document.

cloneNode

cloneNode makes exact duplicates of nodes, and has just one option: true or false. If true, cloneNode will include a copy of all the children from the original node. In the case of our example, true was necessary in order to gain a copy of the text of the paragraph, not just the markup.

With the true option cloneNode copies everything from the original node: applied styles, text, images, even JavaScript references (with the exception of any applied addEventListener). This exact duplication can lead to some issues, as we’ll see in a moment.

Duplicity

One issue in our example is that we now have an exact duplicate of the original node, including its id:

<p id="bees">Busy worker bees.</p>
…
<p id="bees">Busy worker bees.</p>

This is bad: id attribute values should be unique references, and it’s very likely that our page will become deeply confused if we allow things to go on as they are. When creating node clones, you should be careful to check for and create new id values in the copies:

var bees = document.getElementById("bees");
var swarm = bees.cloneNode(true);
swarm.id+= "copy";
document.body.insertBefore(swarm, document.body.firstElementChild);

In this case, we’ve concatenated the word copy to the original id value of the clone.

After we create them, clones go on to live their own lives: altering bees will not affect beescopy, and the reverse is also true: changes to clones do not affect their originals.

Conclusion

cloneNode is an extremely useful method, allowing the web developer to quickly make multiple copies of almost anything and distribute them on the page. Then, those copies need to be manipulated… which is what this series will be looking at next.

Photograph by Annet Voronaya, licensed under Creative Commons

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.