Why is an element empty in IE after being removed from the DOM?

The following HTML and JavaScript are taken from parts of this jsFiddle: http://jsfiddle.net/stephenjwatkins/2j3ZB/3/

HTML:

<p class="source"> Source </p> <div id="target"> <p class="dummy"> Target </p> </div> <button id="transfer-button">Transfer</button> 

JavaScript:

 var sourceEl = $('.source'); var targetEl = $('#target'); $('#transfer-button').click(function() { targetEl.html('<p class="dummy">Transferring...</p>'); setTimeout(function() { // Source element will be empty on second attempt to append targetEl.html('').append(sourceEl); }, 750); return false; });​ 

Note that setTimeout text and dummy text are just for the visual indicator.

As you can see, after the source element is added and removed once from the DOM, IE (all versions) will add an empty element to the DOM with any additional additions; whereas in all other browsers the correct, non-empty element will be added.

Another aspect that adds to the confusion is that sourceEl still has item information (for example, sourceEl.attr('class') returns "source").

I know how to mitigate the problem (e.g. sourceEl.clone() ), but it would be nice to better understand why IE behaves differently to avoid any related issues in the future.

What causes the source element to be uniquely empty in IE after replacing the element?

+4
source share
2 answers

First highlight the important parts:

  • (first click) Accepts the source element and places it inside the target element;
  • (second click) Empties the target element and adds a new child ( p.dummy ) to it, effectively removing source from the DOM;
  • Empties the target element and tries to re-add source , which is no longer present in the DOM.

At first, this does not work in any browser, since the source element has already been removed from the DOM. The “magic” here is the JavaScript Garbage Collector . Browsers see that sourceEl is still in range (inside the setTimeout closure) and does not delete the associated DOM element inside the jQuery sourceEl object.

The problem here is not the JScript implementation (Microsft Javascript implementation) of the Garbage Collector, but the way JScript handles the DOM parsing when setting the innerHTML element.

Other browsers simply separate all of the childNode (which will be compiled by the GC when there are no more active links) and childNode html string passed in the DOM elements, adding them to the DOM. Jscript, on the other hand, will also remove the detached childNode s' innerHTML / childNode s. For an illustration look a violin .

The element, in fact, still exists in IE and is added to the DOM:

enter image description here

It no longer has a childNode .

To prevent this behavior, .clone() element (as mentioned in the question) or .detach() before calling .html() on your parent element if you intend to reuse the element instead of overwriting it.

Here the script using .detach() before overwriting the item works fine in all browsers.

+5
source

In my opinion, IE is behaving correctly, and other browsers are magical to work with. All this happens when you call the line:

 targetEl.html('<p class="dummy">Transferring...</p>'); 

This removes the sourceEl element from the page. Therefore, he is no more. I assume that other browsers remember the DOM object, as there is still a variable referencing it. But IE recognizes this as no longer existing on the page, so it loses the link.

As you mentioned, I would recommend cloning an object when you click. This creates a new object in JavaScript. Fortunately, rewriting a single variable works.

  sourceEl = sourceEl.clone(); 

http://jsfiddle.net/AbJQE/3/

edit You can also delete all existing source source objects before inserting a new one. This fixes the problem to trigger triggers:

 setTimeout(function() { $('.source').remove(); targetEl.html('').append(sourceEl); }, 750); 
+2
source

All Articles