0

I am experiencing a wierd behaviour with jquery-ui and jquery .clone() , remove(). I am using jquery 1.7 and jquery-ui 1.8.16. The problem is when i remove an element from a deep cloned element using remove() function , the remove affects the cloned element AND the corresponding element in the document by removing the draggable properties from the element in the DOM. I'm not sure if i'm doing anything wrong but it seems to me like either my misunderstanding of how clone(true,true) works or a bug in jquery-ui.

consider the following

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js" type="text/javascript"></script>
  <script type="text/javascript">
  $(document).ready(function() {
    $('#testp').draggable();
    //the following line causes the draggable classes to be removed from the document
    //as well as the cloned object ,the expected behaviour is that that #testp will be 
    //removed only from the clone...
          var test = $("#test")
           .clone(true,true)
           .find('#testp')
           .remove()
           .end(); //some more manipulation here
        });
  </script>
</head>
<body>
  <div id="test">
    <p id="testp">some text</p>
  </div>
</body>
    </html>

UPDATE: It seems that .clone(true,true) still keeps some data shared among the clone and the original. Even with changing the ids/applying .draggable() with a class selector and not removing any element from the dom, dragging the clone will move the original and not effect the clone(as one would think). other handlers like click etc ,are cloned correctly

After seeing some posts about issues cloned divs with (true,true) and draggable plugin, i've decided to refrain from cloned divs copying etc and just use detach() and reattach as a workaround.

Note to others who tried clone(true,true) to clone divs with draggable() plugin applied: if you clone(true,true) some data will be copied to the clone and by applying draggable() to it you'll be dragging the original, and i guess that's not what you intened to do. instead do a shallow .clone() and then bind draggable() to the clone.

Avi
  • 155
  • 8

2 Answers2

0

Try separate statements:

var test = $("#test");
test.clone(true,true).appendTo("whatever").find('#testp').remove();

PS: clone() and remove() are in jQuery core. Presence of jQuery UI should not affect them but by all means try without UI installed.

Beetroot-Beetroot
  • 18,022
  • 3
  • 37
  • 44
  • It does not work. i want to assign the cloned element to a variable. and reassign it at a later time.( I don't want to append it to the document yet) var test = $("#test"); var copy = test.clone(true,true).find('#testp').remove().end(); //That last line causes the same behaviour – Avi Feb 28 '12 at 12:35
  • I should also note that other behaviors are retained on the original for example click events are retained. that's i think it's more related to jquery-ui – Avi Feb 28 '12 at 12:45
  • The problem may be due to the use of ids. The clone will have the same ids, so you need to change them after cloning or use classes instead. – Beetroot-Beetroot Feb 28 '12 at 13:07
  • 1
    Note also that the jQuery documentation for `.clone()` includes the proviso "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: ...". This aspect may need to be taken into consideration with `draggable()`. – Beetroot-Beetroot Feb 28 '12 at 13:14
  • Note the comment below in the documentation for clone(): 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. that's why i use .clone(true,true) – Avi Feb 28 '12 at 14:32
  • Indeed, and the draggable() element *may* clone OK with `clone(true,true)` and nothing else. The proviso relates specifically to "objects and arrays within element data". If the cloned element's draggable() characteristics do not clone OK, more specifically if they are not independent of the original element, then you will need undertake the manual copying of deep data as indicated (or otherwise ensure draggable() independence). – Beetroot-Beetroot Feb 28 '12 at 19:04
  • Well as stated i've decided to go another route , but your answers helped me understand more and come to that conclusion. so thx ! :o) – Avi Feb 29 '12 at 10:12
0

Please review : What is the most efficient way to deep clone an object in JavaScript?

Please note that you may have to unbind the events clone and re-apply them during a clone - depending somewhat on how you do it, you may need to unbind the source if you apply the event to the original when you apply if your new apply selection includes the original.

In your case, you are using an id selector, then removing it - it will remove the first instance of the id that it finds.

You may need to do something like:(verbose version for clarity)

var test = $("#test");
var newtest = test.clone(true, true);
newtest.find('#testp').remove();
newtest.attr('id', 'newtest');
newtest.appendTo("#whatever");

Do your rebind here perhaps...

see this example: http://jsfiddle.net/MarkSchultheiss/yfD3r/

Community
  • 1
  • 1
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • Actually it does not remove the ID that's on the dom. only the draggable attributes Actually I'm trying to avoid a rebind that's why this manipulation... What i'm trying to achieve is an editor with draggable elements that retains all it's behaviours while 'ajax navigating' between pages. what i figured out that i can clone the navigator outside the dom and reattach it after ajax completes. problem is that another editor will try to load on some ajax calls , and that's what i'm trying to remove – Avi Feb 28 '12 at 14:35
  • SO, you question has changed it seems – Mark Schultheiss Feb 28 '12 at 14:59
  • NOTE: there is a difference between events and draggable which is more a 'widget' than an event such as 'click' and you may need to re-attached the draggable after you re-insert it from the prior removal from the DOM. – Mark Schultheiss Feb 28 '12 at 15:06