Search code examples
jqueryjquery-datajquery-clone

$.clone() & $.data() strange behaviour


Can someone explain to me why, when I clone an element with jquery .clone(), store it in $(windows).data('myclone') and append this cloned data element to another element, the cloned data present in $(windows).data('myclone') changes? (points toward my newly created element in html inspector)

<li class="clone">
    <button class="file-list-delete"><a href="#">clone this</a>
    </button>
    <input type="file" size="30" id="files" multiple="multiple" name="files" class="upload-files">
</li>
<button id="append">append clone</button>

<script>
    $('.clone button').on('click', function() {
        var cloneNode = $(this).parent().clone();
        $(window).data('cloneNode', cloneNode);
        console.log(cloneNode);
    });
    $('#append').on('click', function() {
        console.log($(window).data('cloneNode'));
        var clone = $(window).data('cloneNode');
        $('.clone').after(clone);
    });
</script>

Here's a fiddle to see it in your console. First created element is just cloned data, then when you append it, it changes it http://jsfiddle.net/50eu0bnp/


Solution

  • You need to clone the clone, otherwise you are reusing the same element.

    You also need to target only one of the elements or you duplicate it after each existing class="clone" element which causes additional copies to be created.

    JSFiddle: http://jsfiddle.net/TrueBlueAussie/50eu0bnp/1/

    $('.clone button').on('click',function(){
       var cloneNode = $(this).parent().clone();
        $(window).data('cloneNode',cloneNode);
    });
    $('#append').on('click',function(){
        var clone = $(window).data('cloneNode').clone();  // Clone the clone
        $('.clone:last').after(clone);
    });
    

    If the elements you clone can vary (they do not at the moment), you need to shift to delegated event handlers as the original $('.clone button') is not connected to the new copies: http://jsfiddle.net/TrueBlueAussie/50eu0bnp/3/

    $(document).on('click', '.clone button', function () {
        var cloneNode = $(this).parent().clone();
        $(window).data('cloneNode', cloneNode);
    });
    

    You also need to address the issue of duplicating id="files" as that is a complete no-no. jQuery will only be able to see the first one (e.g. with $('#files')) as ids must be unique.