Forum Moderators: open
This is my first post here, so I ask in advanced that you please be gentle and excuse my ignorance if I inadvertently trample on any of the posting etiquette policies (both written and unwritten), and please let me know if/when I do screw up, so that I'll know to not do that again.
I thank you in advanced for your graciousness, and now I'll proceed with my issue.
The subject basically say it all: I'm fighting with setInterval. In this post, I'm including 2 iterations of the same code: 1) a bare-bones version (the working code), and 2) a version closer to what I'd like to use in production (although it's still pretty far from production-grade code IMHO).
My goal was (and still is) to partition the code into 3 parts: 1) the initialization code (initHex(...) and fade(...)), 2) the display/canvas handling code (setBgColor(...) and doIt(...) in this case), and 3) the timer code. The reason for the increasing complexity is that I ultimately intend to set up a graphics pipeline for rendering various objects.
The problem, that I'd like to resolve, feels like I'm dealing with some kind of scope issue. The setInterval(...) call in the first code fragment works correctly, but the call in the second code fragment appears to go into while(1) (or do-forever) loop. (I've tested this with several versions of Firefox [most recently with version 3.0.5] and Konqueror [most recently version 3.5.10] using several Unix-like envs [Linux {Knoppix 5.3.1, Slax 6.0.9, DSL, Gentoo}, OSX {Tiger and Leopard}, and BSD {FreeBSD 7.x, and OpenBSD}]; I consistently received the same results.) Also, upon closer inspection (of the second version)--both using document.write(...) calls and FireBug--I noticed h_i always remained 0 whenever the setInterval(...) code ran.
So, how do I resolve this/these issues?
NOTE: Occasionally, I needed to use \[i\] in both code fragments to prevent the forum parser from treating my indexes as style codes. Please let me know if there's another way to do this (without my needing to rename the index variable, i).
<HTML>
<HEAD>
<TITLE>Fader</TITLE>
<SCRIPT LANGUAGE="Javascript">
var hex=new Array('#000000', '#1f1f1f', '#3f3f3f', '#5f5f5f', '#7f7f7f', '#9f9f9f', '#bfbfbf', '#dfdfdf', '#ffffff'), i=0, intervalId; function fadeIn() {
document.body.style.backgroundColor = hex\[i\];
++i;
if (i>=hex.length) clearInterval(intervalId);
}
// 50 ms is good
[b]intervalId = setInterval('fadeIn();', 50);[/b]
</SCRIPT>
</HEAD>
<BODY></BODY>
</HTML>
<HTML>
<HEAD>
<TITLE>Fade In And Out</TITLE>
<SCRIPT LANGUAGE="Javascript">
// dithered hex patterns array
var hex=new Array(), [b]h_i=0[/b], h_ub, myInt, n=8 function initHex(a, b) {
for(var i=0; i<n; i++) {
var tmp=b*(n-i)/n+a*i/n-1, j=Math.floor(tmp/16), k=tmp%16
hex\[i\]=j.toString(16)+k.toString(16)
}
hex[n]="00"
// assert hex.length is proper value (n+1)
if(hex.length!=(n+1)) document.write('initHex: ERROR: Recheck the bounds i and n.')
} // end of initHex
function setBgColor(i) {
// reinterpret i (a color palette value) as a 3-digit, packed, base rdx (the number of elements in hex) value;
// and split off each digit as a separate index
var rdx=hex.length, j=Math.floor(i/Math.pow(rdx,2)), k=Math.floor((i%Math.pow(rdx,2))/rdx), l=i%rdx
// transform those indexes into the corresponding RGB-value
x='#'+hex[j]+hex[k]+hex[l]
document.body.style.backgroundColor=x
document.write('i: '+i+' backgroundColor: '+x+'<BR>')
} // end of setBgColor
function doIt() { setBgColor([b]h_i++[/b]); if (h_i>=h_ub) { h_i=0; clearInterval(myInt); } }
function fade() {
document.open('text/html')
initHex(0, 0x100)
h_ub=Math.pow(hex.length,3)
// NOTE: I keep getting 'document.body is null' errors in FF 3.0.5 unless
// I first write something, before calling setBgColor(...).
document.write('<BR>')
// [b]myInt=setInterval('doIt();', 50)[/b]
//setBgColor(400) // 400 <--> #7f007f
} // end of fade
fade()
[b]myInt=setInterval('doIt();', 50)[/b]
</SCRIPT>
</HEAD>
<BODY></BODY>
</HTML>
Also, I'd like to know why I kept getting 'document.body is null' errors in FireFox 3.0.5 whenever I attempted to change the background color--unless I wrote something (which could be anything other than ' ' or '\t') to the document stream beforehand.
Actually, I get that 'document.body is null' error message in both cases (including when the script executes via the body onload event).
Also, I displayed h_i directly in the document using document.write. h_i increases (as it's supposed to) whenever setInterval(...) isn't called; however, it never changes from 0 whenever setInterval(...) is called.
h_i increases (as it's supposed to) whenever setInterval(...) isn't called; however, it never changes from 0 whenever setInterval(...) is called.
I don't follow. No setInterval = no doit() = no h_i++ ?
Does 'document.body is null' go away if you staticly add contents to body like
<body>Hello world</body>
First, I pruned my debug-output statements from the code I posted, and I attempted to explain/describe some of the tests I ran on the code. For example, following are 2 lines of debug code that I pruned:
function doIt() { document.write('h_i: '+h_i+'<BR>'); ++h_i; if (h_i>=h_ub) { h_i=0; clearInterval(myInt); } }
function doIt() { document.write('h_i: '+(h_i++)+'<BR>'); } Second, I also noticed that occasionally if I wait awhile, while setInterval(...) sends that code off into the ethers, I'll get a weird stack-trace error message. Also, whether or not I receive the stack-trace, I usually have to stop the execution of the script manually, and I usually have to terminate and reload FireFox (because FF doesn't appear to clean up its program state very well after this issue happens). Unfortunately, since I'm just starting to learn JavaScript, I don't know the internals of JavaScript well enough to dig deeper. (Side note rant . . . this is one of those times I wish I were dealing with C/C++ or ASM code. . . . There has to be some kind of way to transform that setInterval(...) call into into its corresponding C or ASM code--since the compiler and byte-code interpreter has to be able to do this.)
Third, no the 'document.body is null' error doesn't go away even with adding the static content. (Btw, it also might help to mention that I turned on console, script, and net logging in FireBug.)
document.write is a sloppy way of doing things. Instead, try using DOM methods to insert nodes into the document.
Also, the yellow triangle icon shows you which threads you have posted in (makes it easier to find threads you're interested in).
Hope that helps.
Also, instead of <script language="JavaScript">, the CORRECT script tag is: <script type="text/javascript">. The language attribute is not valid.
Now, I see--after having checked out the w3c HTML 4.0 and 5.0 standards--that the language attribute was non-standard and was deprecated in the w3c HTML 4.0 standard. (Not that I didn't believe you. I'm a JS n00b [and a specialist in other languages], so I'm just trying to get my bearings--gotta crawl and slurp some Gerber's pureed beans before I'm mature enough to bolt to Chick-fil-a for some waffle fries.)
Concerning the document.write(...), do you mean I should do something like the following?
function echo(s) {
return [b]document.getElementById("response").appendChild(document.createElement("div")).appendChild(document.createTextNode(s));[/b]
}
</script>
</head>
<body>
<div id="[b]response[/b]"></div> Anyway, I thought that everything in <HEAD> . . . </HEAD> gets loaded before the onLoad event triggers. In fact the author stated (on pg 95), "You should normally place all functions at the top of the page, or more accurately, in the <HEAD></HEAD> portion of the document. This action forces JavaScript to evaluate your functions before it continues laying out the page. With this practice you guarantee that when the browser comes across an event handler in the HTML portion of the page, it will succeed in calling the function associated with that event if it occurs."
So, basically, do I need to scrap my current approach for invoking setInterval(...) and instead use a closure to implement the behavior I want (with respect to setInterval(...))?
The echo() function looks Ok
Anyway, I thought that everything in <HEAD> . . . </HEAD> gets loaded before the onLoad event triggers
Loaded yes, executed maybe, but not delayed executions as per setInterval()