Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clone elements that have been bound by a jQuery UI Widget?

The following code fails to properly clone the input element. Clicking/focusing on the cloned input opens the datepicker on the original input.

http://jsfiddle.net/musicisair/YUkZw/

<input>
<script>
    var input = $("input").datepicker();
    $("body").append("<br>Input 2: ").append(
        input.clone(true);
    );
</script>

Is there a correct way of cloning elements that have been bound with a jQuery UI widget? If so, what is is?

like image 899
David Murdoch Avatar asked Mar 15 '12 18:03

David Murdoch


1 Answers

Normally, any event handlers bound to the original element are not copied to the clone. The optional withDataAndEvents parameter allows us to change this behavior, and to instead make copies of all of the event handlers as well, bound to the new copy of the element. As of jQuery 1.4, all element data (attached by the .data() method) is also copied to the new copy.

However, objects and arrays within element data are not copied and will continue to be shared between the cloned element and the original element. To deep copy all data, copy each one manually:

var $elem = $('#elem').data( "arr": [ 1 ] ), // Original element with attached data
    $clone = $elem.clone( true )
    .data( "arr", $.extend( [], $elem.data("arr") ) ); // Deep copy to prevent data sharing

As of jQuery 1.5, withDataAndEvents can be optionally enhanced with deepWithDataAndEvents to copy the events and data for all children of the cloned element.

Source: http://api.jquery.com/clone/

I believe you are looking for the code above that actually copies the data associated with an element rather than sharing the data between elements.

Update

After messing around a few minutes with this here's what I came up with:

//create original datepicker
var $input = $("input").datepicker(),

//clone the datepicker, copy the data from the original, and change the ID of the new element
    $clone = $input.clone(true).data( "datepicker", $.extend( true, {}, $input.data("datepicker") ) ).attr('id', 'test-id');

//now change the references in the data for the clone to point to the clone
$clone.data('datepicker').input = $clone;
$clone.data('datepicker').id = 'test-id';


//add the clone to the DOM
$("body").append("<br><br><br>Input 2: ").append(
    $clone
);
​

And a demo: http://jsfiddle.net/YUkZw/5/

like image 137
Jasper Avatar answered Sep 21 '22 07:09

Jasper