Why is element empty in IE after being removed from the DOM?
dom, internet-explorer, javascript, jquery
Solution
First let's highlight the important parts:
- (first click) Takes the `source` element and put it inside the `target` element;
- (second click) Empties the `target` element and appends a new child (`p.dummy`) to it, effectively removing `source` from the DOM;
- Empties the `target` element and tries to re-append `source`, which is no longer present in the DOM.
At first look, this wouldn't work in any browser as the `source` element has already been removed from the DOM. The "magic" here is JavaScript's Garbage Collector. Browsers see that `sourceEl` is still scoped (inside the `setTimeout` closure) and do not trash the referenced DOM element inside of the `sourceEl` jQuery object.
The issue here is not JScript (Microsft's Javascript implementation)'s Garbage Collector, but rather how JScript handles the DOM parsing when setting an element's `innerHTML`.
Other browsers will simply detach all `childNode`s (whose will be collected by GC when there are no more active references) and parse the passed html string into DOM elements appending them to the DOM. Jscript, on the other hard, will also erase the detached `childNode`s' `innerHTML`/`childNode`s. Check this fiddle for an illustration.
The element, in fact, does still exist in IE and is appended to the DOM:
It just has no `childNode`s anymore.
To prevent this kind of behavior, `.clone()` the element (as mentioned in the question) or `.detach()` it before calling `.html()` on its parent, if you intend to re-use the element instead of "overwriting" it.
Here's a fiddle using `.detach()` before the element is overwritten, works fine in all browsers.
Problem
The following HTML and JavaScript is 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 the setTimeout and dummy text is there simply for a visual indicator. As one can see, after the source element is appended and removed once from the DOM, IE (all versions) will add an empty element to the DOM upon any further appends; whereas, all other browsers will add the correct, non-empty element. Another aspect that adds to the confusion is that the sourceEl still has element information (e.g. `sourceEl.attr('class')` will return "source"). I know of methods to mitigate the issue (e.g. `sourceEl.clone()`), but it would be nice to have a better understanding as to why IE is behaving differently to avoid any related problems in the future. What is causing the source element to be uniquely empty in IE after once replacing the element?