Wednesday, 22 September 2010

iframes and objects

This morning I was doing some more work on my photo website. I was happy to see that my lightbox close icon was now showing up again in Chrome, so the reason it wasn't displaying before must have been Chrome bugginess rather than my own fault.

Then I had a similar thing with IE6. The lightbox was displaying at a small size, so I undid the changes I made to the code yesterday, refreshed the page a few times, but it was still the same. I then started up Visual Web Developer Express so I could debug the problem, but when I loaded up the site for debugging, it displayed okay!

I was worried that it might be that the site only works properly in IE6 when Visual Web Developer Express is worried, so I closed that and checked the site, but it was still working okay. I just don't understand how computers can be so illogical.

Next I changed the page headers so that it would be sent as html instead of XML + XSLT to IE. But when I refreshed the page, I just got the HTML in the style that IE uses to display an unstyled XML document (i.e. like viewing source). So I installed Fiddler2 to double check the headers that IE was receiving from the page, but when I restarted IE, the page now rendered correctly!

I think that probably IE must cache the content-type of a page, so if you refresh a page, it will use the content-type that the page had when it originally requested it.

After doing this, I found that my page still won't work properly when moving an object in the DOM in IE, despite working in my test page.

I spent the rest of the morning debugging this, and creating a test page:

I found that in IE, the google maps page stops working when you move the object in the DOM, and the map has been initialized using a callback function. Strange.

On my test page in IE6, it will create an object in the page, but it won't load the object's contents. Strangely, it works okay on my real website (where I use jquery to create and append the object) though.

In IE8, it won't load the Amazon home page in an object. Presumably it doesn't like it because it's a different domain to the containing page.

In Chrome and Firefox (but not IE), moving an object in the DOM reloads it.

In Chrome, when setting the display of an object to 'none', and then setting the display back to 'block', this will cause the object to reload its contents.

I found this bug report for Firefox, which says:
Whenever an iframe node is pulled from the DOM tree, the contentWindow is set to null, forcing a reload of the iframe's content when it is placed back into the
DOM tree.
So I tried cloning the iframe, using both shallow ( iframe.cloneNode() )and deep cloning ( iframe.cloneNode(true) ), but the cloned iframe always had a contentWindow of null (even though the iframe I was cloning from had a contentWindow of DOMWindow.

I also tried assigning the contentWindow of the iframe to a variable before moving it, then setting the contentWindow of the moved iframe to the variable, but this didn't work. I tried both iframe.contentWindow = oldContentWindow and iframe.setAttribute('contentWindow', oldContentWindow). Neither worked, and doing the same thing with contentWindow.document didn't work either.

It seems that storing the old value in a variable works okay, but setting a new value for contentWindow or contentWindow.document doesn't work.

The only way I can think of that you could move an iframe (or object) in the DOM without it looking like it had reloaded is to keep track of all relevant interactions with the iframe before it is moved, and then recreate these interactions programatically after moving it. E.g. if the iframe contained just a simple scrolling page, you would have to get the scroll positions before moving the iframe, then set them again after moving it.

Looking into that took all morning and a bit of the afternoon. I went out in the garden and took some photos of Red Admirals, then spent the rest of the afternoon and most of the evening working on my geo clustering script.

No comments: