Category Archives: DOM API

Iframe reloads when moved around the DOM tree

I had a great idea. And to implement it, I needed to do DOM manipulation of an element that contains an IFRAME. It’s simple right? Just do something like

document.getElementById(“to”).appendChild(document.getElementById(“elementwithiframe”));

This actually worked. It even works if the iframe is generated using document.write that is part of an external javascript. I was almost done with my project. When I was testing out another javascript that creates an iframe, I ran into the first issue. The elementwithiframe moved by the iframe was blank.

I observed that in one case the javascript creates an iframe that has the src attribute and loads the iframe content from a URL. In another case, it creates the iframe and opens the iframe’s document and writes the content and closes the iframe. The second case is where I had the problem. This happens in both Firefox and Safari.

I wasted a lot of time on this issue. I even came up with a workaround for the second case. The workaround is to first get the head and body elements of the iframe before it’s moved and after the move, copy it back. In fact it worked perfectly fine. But I was still curious why the behavior is different in both case. I even downloaded WebKit source and browsed through it, didn’t find the exact issue, but the dom API has it’s issue which I will tell in a few minutes.

Then, after searching on Bugzilla@Mozilla, I found a bug that gave more details. Apparently, when an iframe is moved around the DOM tree, it’s refreshed. So, if an iframe has an src element, it’s just refreshing the frame again. This means the document is loaded twice. But when the iframe is created by opening the document and writing the content, that content is lost when the DOM is moved. It doesn’t seem to execute the script again (which is probably what is desired as otherwise, there would then be two frames). More importantly, the script element that generated the iframe should not execute the second time because the iframe is generated using document.write. So, once a document is loaded, calling document.write can have unwanted consequences. Anyway, I wasn’t observing this, so hopefully moving script element with src attribute around doesn’t execute it again.

Net net, moving an iframe around the DOM model makes it refresh and in case where the document content is filled using javascript, the iframe is going to lose it’s content unless the hack I mentioned above is done.

Looking at the above Mozilla bug and also the WebKit code I looked at made me realize that part of the problem is with DOM specification which states that since a node can have only one parent, moving around requires removing the node from the parent and then adding it back. But to remove the node, usual logic used is removeNode api. So, in case of an iframe element, calling the removeNode seems to have the adverse impact of clearing up the content (why this happens only for iframe but not other types of elements like div beats me, but may be that has to do with the fact that iframe represents a complete document altogether and not cleaning up immediately when the removeNode is called can have memory issues).

Had the apis to move the node (appendChild, insertBefore, insertAfter) were not required to do the remove as per the spec, then this would have been a simple move without destroying the iframe content. But again, I don’t know if I should say that the DOM api is wrong because as I mentioned, this works for other types of elements, not just iframe.

The fact that this bug was filed on 2004-08-03 and it’s open to this day reflects the complexity of fixing this issue which I don’t hope anytime soon. Someone actually provided a patch in 2009, but it’s not incorporated yet because of concerns on what it might break in several other areas.

After giving this some more thought, I abandoned my project which I thought I got a master idea :).

3 Comments

Filed under DOM API, IFRAME, javascript