How to clone an element in Javascript?

Asked

Viewed 8,665 times

14

Is it possible to obtain an exact clone of a given HTML element? so that the clone contains all properties exactly the same?

If there is, I would like to know how to proceed to perform this clone, and also understand how it would be acting, how it would be cloning, ie a more conceptual theory covering about the clone itself.

  • Possible duplicate: http://answall.com/questions/857/howto create a copy of an object/

  • It’s definitely not a duplicate @Gabrielsantos. I don’t see any related content here with there. Pay attention to the context and you will see that they are different things.

  • Sorry. It was a mistake.

  • Magina, @Gabrielsantos, it’s okay. Feel free to fulfill your role of signaling duplicate issues :)

2 answers

11


Answering the question: Yes, there is a possibility of getting a clone, using native javascript, which would be, or not (you’ll already know why) a faithful clone exactly the same containing all the properties of the cloned element.

Concept/Explanation: The HTML elements in their format as you can see, like HTML code between tags, they are not just that. Each element is one Node, which is stored inside the DOM(Document Object Model) where there would be contained all the information, functions available for use, reference, attributes, values, among others, summarizing, everything that an element is, is stored in DOM, without it we would not be able to access the properties of the elements directly. So to get an identical and exact copy of another element, we can clone the Node of him, in this way we would be cloning what he is.

Information/Examples/Practice: Each Node has a native Javascript function called cloneNode(), where now I explain why I said "or not" right at the beginning about making a faithful clone, which would be in case the parameter deep of function cloneNode(), which is a required parameter, ie you have to inform you, we will know this function:

cloneNode([deep])

Arguments

deep (Boolean) required

If true(true), duplicates the subtree of the Node as if he were himself.

If false(false), only copies the node (and its attributes if it is an element).

Description

Create a copy (duplicate) of this Node, including all attributes, and their respective values, and attributes, including those that are not defined but contain a standard(default) value in the DOM. The Node duplicate, there is no Father(parent), i.e., the parentNode is null, only while you do not include it in the document, as for example using appendChild.

However, if the argument deep be true(true), then the sub-tree of the Node will also be duplicated.

Additional Information

By cloning a subtree that’s like readonly(read-only), would result in a sub-tree that cannot be modified.

The attributes of Node element, when being cloned, are also copied, including the standard attributes(default), but the element text is not copied, only if the argument deep is true(true).

Attention, Important Information about Events(credits to @bfavaretto):

Clone will not have the events of the cloned element, whether you assigned it as property or with addEventListener (most recommended methods, by the way), the only way that cloning works with events is when the event is inline that is to say: <div onclick=alert('foo')> for example.

If you want to understand better, there is an example Here

Return Value:

The Node duplicated (cloned).

Well, now that we know the function, let’s practice:

Testing with deep clone (deep = true parameter):

Note: Please use an element that has children for a better understanding.

var seuNode = document.getElementById('IDdoElementoQueTemFilhos'); //usei getElementById() por opção você pode resgatar a referência do seu node como quiser.
var clone   = seuNode.cloneNode(true); //aqui você terá seu clone armazenado em variável mas ainda não incluido no Documento, sem parentNode.
document.body.appendChild(clone); //você pode dar append onde quiser, utilizei o body.

Testing with clone only (deep parameter = false):

var seuNode = document.getElementById('IDdoElementoQueTemFilhos'); //usei getElementById() por opção você pode resgatar a referência do seu node como quiser.
var clone   = seuNode.cloneNode(false); //aqui você terá seu clone armazenado em variável mas ainda não incluido no Documento, sem parentNode.
document.body.appendChild(clone); //você pode dar append onde quiser, utilizei o body.

Note that for example 1, you got the complete clone of it, including the children it has, i.e., its subtree.

For example 2, you only got the clone of the isolated element, only it, without getting the copy of the children too (subtree).

Depending on your use you can switch between the two cloning methods. There are also other ways even using the .clone() jQuery, however, I consider it best to utilize this way that has clone fidelity of a Node and is native javascript, not requiring external plugins.

  • 2

    Visually, great, the cloneNode resolves. But beware, because it does not copy events assigned to cloned elements.

  • Are you sure @bfavaretto ? performed this test right now and I was successful in cloning with event as well, see for yourself http://jsfiddle.net/9Aja7/

  • It works in this case because you passed the inline Listener as attribute. If you assign as property or with addEventListener (most recommended methods, by the way), the event is not cloned. http://jsfiddle.net/9Aja7/1/

  • How sad @bfavaretto, it discouraged me a little bit, but at least this is important information that I will add to the answer.

  • I understand the discouragement... In the case of addeventlistener, it is not so simple to get around this. jQuery can because I totally abstract this part of events, so it keeps a list of everyone’s events.

3

In jQuery there is the method jQuery.clone which allows cloning elements (with or without their respective events)

Consider the following example

HTML structure

<div class="wrapper">
    <div class="exemplo">Uma div</div>
</div>

Javascript code

// Evento simples de clique
$('.exemplo').on('click', function() {
    alert('Evento click');
});

// Clona o elemento com classe "exemplo"
var $clone = $('.exemplo').clone();

// Clona o elemento com classe "exemplo" juntamente com seus eventos
var $cloneComEventos = $('.exemplo').clone(true);

// Adiciona os elementos clonados no elemento wrapper
$('.wrapper').append($clone);
$('.wrapper').append($cloneComEventos);

The wrapper element will have a total of 3 elements, the first (original) and third (your copy) will have click events

In practice: http://jsfiddle.net/wTdg2/

Browser other questions tagged

You are not signed in. Login or sign up in order to post.