[HTML/JS] the joys of breaking stuff... endless loop

Elledan

[H]ard|DCer of the Month - April 2010
Joined
Oct 18, 2001
Messages
15,913
index.html:
Code:
<html>
<head>
	<title>JS/HTML no-refresh interface test</title>
</head>
<body bgcolor="black" text="white" link="white" vlink="white" alink="green">
	<iframe id="ifr" name="ifr" src="main.html" width="0" height="0" border="0"></iframe>
	<p>
	<script type="text/javascript">
		function echo (str) {
			document.write("string...");
			document.write(str);
			document.write("<br>done");
			alert(str);
		}
	</script>
	</p>
</body>
</html>
main.html:
Code:
<script type="text/javascript">
	var strings = new Array();
	strings[0] = "First String";
	strings[1] = "Second String";

	window.parent.echo(strings[0]);
	window.parent.echo(strings[1]);
</script>

As you can see, main.html is loaded in an invisible iframe in index.html. A function in main.html then calls a function in index.html which then prints the received string and shows an alert.

The problem is that right with the first run the thing hangs, probably in the echo() function. It prints the things it has to print (although on a new 'page'), gives the alert, and then just pretends to be busy.

Hmm... it now gives an interesting error in the JS Console right after it hangs:
Error: window.parent has no properties
It's as though the first document (index.html) has become unavailable.

Now, the question is: what are the stupid/boneheaded/forbidden/obvious things I'm clearly overlooking? ^_^

I've been testing this all in Firefox 1.5 RC1, BTW.


Off-topic: look at this:
Error: Error in parsing value for property 'font'. Declaration dropped.
Source File: http://www.hardforum.com/editpost.php?do=editpost&p=1028525044
Line: 18
;)
 
document.write is meant for adding HTML to a document as it is loading, or for creating an entirely new doc from scratch. When you call it on an existing document, it simply clears that document and begins a new one.

So, when you call echo from your iframe, it clears your parent document. The script in the iframe doesn't disappear immediately (despite the iframe no longer existing), but its reference to window.parent is no longer meaningful. The busy/loading thing is from the newly created document never being closed with document.close().

To manipulate an existing doc, you have to use DOM methods. Try this:
Code:
		function echo (str) {
			var p=document.createElement('p');
			var t=document.createTextNode(str);
			p.appendChild(t);
			document.body.appendChild(p);
			alert(str);
		}
 
Well, I solved the previous problem No more issues there, fortunately ^_^

However, in my enduring attempts to break stuff, I've come across the following problem:

index_f.html:
Code:
<html>
<head>
	<title>JS/HTML frames no-refresh interface test</title>
</head>
<frameset rows="0%, 100%">
	<frame name="data" src="main_f.html" scrolling="no" noresize frameborder="0" marginheight="1">
	<frame name="content" src="index2_f.html" scrolling="auto" noresize frameborder="0" marginheight="1">
</frameset>
</html>

main_f.html:
Code:
<script type="text/javascript">
	var Alayout = new Array();
	var Aprime = new Array();
	var Asub1 = new Array();
	var Asub2 = new Array();	
	var openStr = '<table bgcolor="#3399FF" width="100%">';
	var endStr = '</table><br>';
	var bufferStr = '';
	
	Alayout[0] = '<tr>\n\t<td>\n';
	Alayout[1] = '</td>\n</tr>';
	
	Asub1[0] = 'First String';
	Asub1[1] = '';
	Asub2[0] = 'Second String<br><a href="main2.html" target="data">Next</a>';
	Asub2[1] = '';
	
	Aprime[0] = Asub1;
	Aprime[1] = Asub2;
	
	top.content.clear();
	
	for (i = 0; i < Aprime.length; i++) {
		bufferStr += openStr;
		for (j = 0; j < Alayout.length; j++) {
			bufferStr += Alayout[j];
			bufferStr += Aprime[i][j];
		}
		bufferStr += endStr;
	}
	bufferStr += endStr;	
	top.content.echo(bufferStr);
</script>

index2_f.html:
Code:
<html>
<head>
	<script type="text/javascript">
		function clear () {
			document.getElementById('td0').innerHTML = '';
		}
		
		function echo (str) {
			document.getElementById('td0').innerHTML += str + "<br>";
		}
	</script>
</head>
<body bgcolor="#55CC88" text="white" link="white" vlink="white" alink="green">	
	<p>
	<font size="+3" face="arial, helvetica, sans-serif">Experimental...
	<table bgcolor="white" width="100%">
		<tr>
			<td id="td0">
			</td>
		</tr>
	</table></font>
	</p>
</body>
</html>

The problem is the following error message:
Error: top.content.clear is not a function

This is quite frustrating; the navigating through the frames apparently works fine, but it refuses to recognize both functions in index2_f.html, even though these worked just fine with the iframe... *sigh* :(
 
You seem to be assuming that index2_f will be fully loaded and parsed by the time main_f calls top.content.clear()... an assumption now proved false.

Make use of onload handlers (in either or both frames), or object detection ( if ( typeof(top.content.clear) == 'undefined') {setTimeout(tryAgainALittleBitLater, 1)} ).
 
I see. With the iframe the page with the functions being called would obviously have been loaded already. Should have seen that one coming.

The object-detection/time-out method sounds good to me :)

[edit]: object-detection didn't work at all. It simply told me that such a thing (top.content.clear()) didn't exist and quit.

I encapsulated the code in main_f in a function render() which is called by an onload call in index2_f, which works fine :D

Thanks for you assistance! ^_-
 
If, in your detection, you included the parentheses after top.content.clear(), then you'd still just be trying to call the function. Gots to look at only the function-object.

Jam this in as main_f (and adjust the frameset so you can see it's output):
Code:
<html>
<body>	
<script type="text/javascript">
function foo(){
  if( typeof(top.content.clear) == 'undefined'){
    document.body.innerHTML+="Not ready yet<br>";
    setTimeout(foo,1);
    }
  else{
    top.content.echo("It's Ready!!!");
    }
  }
foo();
</script>
</body>
</html>
Running locally, it'll only give you one or two "Not ready yet". With everything on a remote server, you can get a whole bunch. :)
 
Actually, I first tried it without the parentheses, with as result Firefox taking up 100% processing time, nearly locking up the system until I was given the option to terminate the script :p
 
Yeah, a too-short timeout could do that -- it spends all its effort checking if things are loaded, and no effort goes toward actual loading. The one-millisecond timeout I used is a bit extreme, 5 or 10 milliseconds is more reasonable.
 
HeThatKnows said:
Yeah, a too-short timeout could do that -- it spends all its effort checking if things are loaded, and no effort goes toward actual loading. The one-millisecond timeout I used is a bit extreme, 5 or 10 milliseconds is more reasonable.
I used 50 or 500 ms. Can't quite remember :D

The onload method is a lot more elegant, though, and fits better with the layout I had in mind, with all new page requests passing through a function in index2_f, which then changes document.location in the data-frame.
 
Back
Top