PDA

View Full Version : DOM reloading problems in Firefox



codeexploiter
02-06-2008, 03:55 AM
Hi,

I was working with an AJAX test page and having some problems with a DOM loading routine I've tried. The scenario is something like this.

There are 3 pages involved in this. The first page issues an AJAX request to the second page. The second page has some div elements and an iframe which loads the 3rd page. The 3rd page has nothing but a script section in which I've declared a JS variable.

In other words the result of the AJAX call will be the content of 2nd page which will be put into a div element in page 1 using innerHTML, which in turn will load the 3rd page via iframe. What I am trying to do is after loaidng the 3rd page in the div container I accessed the JS variable that I declared from the first page successfully. After I've removed the div content (the 3rd page contents from the div) and then loaded the DOM again in the div and tried to access the JS variable again and found that it has a value undefined.

I am able to get the JS variable value correctly even after the 2nd reloading of DOM when I call location.reload(). But I am looking if this can be done without the reloading of the page in either way (from cache or from server).

You can see my code below




Filename : 1.htm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Untitled Document</title>
<script type="text/javascript" src="yahoo-min.js"></script>
<script type="text/javascript" src="event-min.js"></script>
<script type="text/javascript" src="connection-min.js"></script>
<script type="text/javascript">
var handleSuccess = function(o){
document.getElementById('container').innerHTML = o.responseText;
}

var handleFailure = function(o){
alert('ajax call failed');
}

var callback =
{
success:handleSuccess,
failure:handleFailure
};

var sUrl = "2.htm";

function makeRequest(){
var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
}

function removeDom(){
document.getElementById('container').innerHTML = '';
location.reload(false);
}

function detectEdObj(){
alert(window.frames['iframe_EDITR'].k);
}
</script>
</head>
<body>
<div id="container">

</div>
<br><br>
<form>
<input type="button" onclick="javascript: makeRequest();" value="load dom"><input type="button" onclick="javascript: removeDom();" value="remove dom">
<input type="button" onclick="javascript: detectEdObj();" value="Detect JS Variable">
</form>
</body>
</html>




Filename : 2.html

<div id="EDITR">
<form>
<iframe name="iframe_EDITR" width="784" height="10" frameborder="0" src="3.htm"></iframe>
</form>
</div>




Filename : 3.htm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Untitled Document</title>
<script type="text/javascript">
var k = 99;
</script>
</head>
<body>
</body>
</html>


Let me know if you need any more information about this. You can find my test files as attachment. Put all the files in the same folder and view 1.htm first click 'load dom' button then "Detect JS Variable" button then 'remove dom' button. Then again 'load dom' button and "Detect JS Variable" where you can see the problem. The aim is If it is possible I would like to get the variable values after the reloading without doing a whole page reload.

In my case I've accessed these files through my web server

Regards

Codex

jscheuer1
02-06-2008, 05:12 AM
Mmm, I don't like relying on so much code like that, where I cannot fairly easily be sure of what is happening. But, no matter, I just happened to have an AJAX routine handy that I do understand, so I used that.

Now, when I do this, it all works out fine in Opera 9.24 and IE 7. FF is a problem, and it looks like a bug to me.

First though, you should realize that you aren't really doing anything to the DOM here, it is all innerHTML. And the form on 2.htm appears to be irrelevant.

What I did basically was to replace your yahoo stuff with an AJAX routine that also works locally, all yours did was fetch 2.htm to the innerHTML of the container div anyway.

Once it is fetched, of course k=99. If you then do:


document.getElementById('container').innerHTML = '';

without reloading, and then fetch the external content again, k=99 - except in FF, where it is undefined. Here is what makes me think it is a bug - I changed this:


function detectEdObj(){
alert(window.frames['iframe_EDITR'].k);
}

to:


function detectEdObj(){
if(window.frames['iframe_EDITR'])
alert(window.frames['iframe_EDITR'].k);
else alert('iframe_EDITR not found');
}

Now, if I load the external content, then:


document.getElementById('container').innerHTML = '';

and then detectEdObj(), I get:

'iframe_EDITR not found'

except in FF, where I get:

undefined.

This means that although the iframe is no longer on the page, it is still part of the window.frames object in FF, or is just hanging around somewhere in javascript limbo waiting for the garbage collector to get rid of it. In either case - in FF - when it is loaded again, it is as though it were already there and at the same time not. Hence the bug/error.

codeexploiter
02-06-2008, 05:54 AM
Thanks John for the answer. It seems that it is a bug, I've developed another simple version of the problem without using AJAX in it.



Filename: 2.htm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title> </title>
<style type="text/css">

</style>
<script type="text/javascript">

var add = function(){
var str = "<div><iframe frameborder='0' width='300' height='100' src='1.htm' id='ifr' name='ifr'></iframe></div>"
document.getElementById('main').innerHTML = str;
}

var remove = function(){
document.getElementById('main').innerHTML = '';
alert('After emptying the innerHTML of the container the frame is '+ window.frames['ifr']);
}

var show = function(){
if(window.frames['ifr'])
alert(window.frames['ifr'].myvar);
else alert('frame is not present');
}
</script>
</head>
<body>
<div id="main">

</div>
<form name="f1">
<input type="button" value="Add" onclick="javascript: add();"/>
<input type="button" value="remove" onclick="javascript: remove();"/>
<input type="button" value="show" onclick="javascript: show();"/>
</form>
</body>
</html>





Filename : 1.htm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title> </title>
<style type="text/css">

</style>
<script type="text/javascript">
var myvar = 1000;
</script>
</head>
<body>
<h1>1.htm</h1>
</body>
</html>


If you browse 2.htm then click on Add, Show, Remove, Add and Show buttons respectively the problem can be viewed..

I've checked this in the following browsers:

Opera 2.5 - passed
MSIE 7.0.5730.11 - passed
Safari for Windows 3.0.4 - passed
Mozilla Firefox 2.0.0.11 - Failed
Flock 1.0.8 - Failed

As I've mentioned a page reload will eliminate this problem but for my case the page is too heavy and would like to avoid a page reload if that is possible.

jscheuer1
02-06-2008, 06:25 AM
This suddenly reminded me of another problem with iframes I had awhile back. Try this detection function:


function detectEdObj(){
for (var f=window.frames, i = f.length-1; i > -1; --i)
if(document.getElementsByTagName('iframe')[i].name=='iframe_EDITR')
alert(f[i].k);
}

Works here.

codeexploiter
02-06-2008, 07:02 AM
John Thanks a lot. It works perfectly for me in my case.

jscheuer1
02-06-2008, 07:33 AM
You're welcome. Interestingly, even this:


function detectEdObj(){
for (var f=window.frames, i = 0; i < f.length; ++i)
if(f[i].name=='iframe_EDITR')
alert(f[i].k);
}

and this:


function detectEdObj(){
for (var f=window.frames, i = f.length-1; i > -1; --i)
if(f[i].name=='iframe_EDITR')
alert(f[i].k);
}

work. Both of which are 'safer' and more honest ways of going about it. The second one is only useful if you expect there to be a large number of iframes with the one you are interested in being near the end of the list. In which case:


function detectEdObj(){
for (var f=window.frames, i = f.length-1; i > -1; --i)
if(f[i].name=='iframe_EDITR'){
alert(f[i].k);
break;
}
}

could be even better.

Just be sure not to lose sight of the chance of having more than one iframe with the same name, although this 'bug' doesn't appear to create that, other coding (hard or scripted) can.

codeexploiter
02-06-2008, 08:35 AM
The smaller the better and thanks again John for the detailed help :). Anyway this one seems to be an interesting problem..