PDA

View Full Version : pausescroller - variable scope



bcswebstudio
04-26-2006, 04:38 PM
Again, I really like the pausescroller. It's just about perfect, and I've extended it as outlined in another post.

I'd like to, however, rein in the use of global variables and requiring that pausescroller be instantiated outside of any other functions. The reason behind this (besides just good code practice) is that I'm build my data array from an XML document. Sure IE has an async=false, but to my knowledge Mozilla does not: there will be no way to delay the instantiation of pausescroller until after data loads without calling it from within a function at the time of data availability.

One thing that eludes me are these lines:


var scrollerinstance=this;
if (window.addEventListener) //run onload in DOM2 browsers
window.addEventListener("load", function(){scrollerinstance.initialize()}, false)

Is that adding an onload event to "window" and not to the obj pausescroller itself? Does window.onload fire any time other than, say, body.onload?

Any tips on this?

Twey
04-26-2006, 04:41 PM
Sure IE has an async=false, but to my knowledge Mozilla does not: there will be no way to delay the instantiation of pausescroller until after data loads without calling it from within a function at the time of data availability.Do you mean using XMLHttpRequest? If so, yes, send() has an optional fourth parameter, specifying whether or not to use asychronicity.

Is that adding an onload event to "window" and not to the obj pausescroller itself? Does window.onload fire any time other than, say, body.onload?As far as I know, body.onload doesn't actually exist; it's merely a proxy for window.onload. I don't believe that the pausescroller has the capability to handle events.
I'd like to, however, rein in the use of global variables and requiring that pausescroller be instantiated outside of any other functions. The reason behind this (besides just good code practice) is that I'm build my data array from an XML document.Yes, it could do with a once-over. Most of the scripts here at DD could.

bcswebstudio
04-26-2006, 04:57 PM
Hmm.. Having spent 5 yrs on M$ IE, I'm new to gecko. I just copied this example from a mozilla-reference and went with it:


function loadXML() {
//load xml file
// code for IE
if (window.ActiveXObject) {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load("data/docketdata.xml");
prepscroll();
}
// code for Mozilla, etc.
else if (document.implementation && document.implementation.createDocument) {
xmlDoc= document.implementation.createDocument("","",null);
xmlDoc.load("data/docketdata.xml");
xmlDoc.onload = prepscroll;
} else {
alert('Your browser cannot handle this script');
}
}

I find it very interesting (apparently creating a new "document" but not specifically an XML engine as in IE), but a bit difficult to research with this sort of abiguity.

Well, the general flow for my script would go something like:
1- prep the screen
2- load xml, convert to js array
3- initialize and fire up the scroller


As far as I know, body.onload doesn't actually exist; it's merely a proxy for window.onload. I don't believe that the pausescroller has the capability to handle events.
I agree with you there (body.onload == window.onload). What I was referring to by asking was more how you can assign and expect an onload event handler to fire without that script being executed-- but then that's where "new pausescroller()" comes into play I see.

I'm very interested in this and would love any tips you can provide. If I come up with some changes which I see as improvements, I'll be sure to voice them here.

Twey
04-26-2006, 05:46 PM
Aha, I see. The other way (the one I thought you meant in the first place) is to use XMLHttpRequest to get the document:
var xh = new XMLHttpRequest();
xh.open("GET", "data/docketdata.xml", false);
xh.send(null);
xmlDoc = xh.responseXML;
prepscroll();

bcswebstudio
04-26-2006, 06:48 PM
Ok! Now I think I'm back on track again; thanks for the more universal, standard, I-should-have-known-or-easily-found-this XMLHttpRequest object. With it (and with synchronous load), I am able to load xml, create an array, and pass that array in.

I'm not certain how the setTimeouts are working properly... They look something like this:


pausescroller.prototype.initialize=function(){
...
var scrollerinstance=this;
setTimeout(function(){scrollerinstance.animateup()}, this.delay);
}

What's confusing me is how is it that a variable definition for scrollerinstance, local to the new method "initialize" of pausescroller, can be referenced later by setTimeout (which works exclusively with global references).

Twey
04-26-2006, 10:03 PM
Good question, and I can honestly say that I haven't a clue. You're right, that shouldn't work. If you have trouble with it, try making it global, or a property of window.

bcswebstudio
04-26-2006, 10:10 PM
You're right, that shouldn't work.
Well, there don't seem to be any issues with it... and "if it ain't broke.."
I think it must have something to do with the fact that it's wrapped in "function() {...}", and it's also not in quotes: it must be making some "ethereal operating code snippet" that is magically tied to the delayed execution of setTimeout.

But I'm sure we've all had issues with quotes, evals, and making global variables or properties of the window object in order to get around the setTimeout requirements... I am going to remember this solution, though-- it looks really cool, doesn't it?

thanks for your help

Twey
04-26-2006, 10:17 PM
It does.
I think it must have something to do with the fact that it's wrapped in "function() {...}", and it's also not in quotesThat's just a standard function definition. (function(a,b){return a+b}) returns a Function object of two arguments that returns the sum of them. It's interesting because I didn't know Function objects could be passed to setTimeout(), I always thought it had to be a string.

mwinter
04-27-2006, 02:16 AM
I agree with you there (body.onload == window.onload).As I recall, neither Firefox, MSIE, nor Opera do anything with an onload property on the body object. The onload property of the window object is synonymous with the onload attribute of the body element, but that's all.



I'm not certain how the setTimeouts are working properly... They look something like this:



pausescroller.prototype.initialize=function(){
...
var scrollerinstance=this;
setTimeout(function(){scrollerinstance.animateup()}, this.delay);
}
What's confusing me is how is it that a variable definition for scrollerinstance, local to the new method "initialize" of pausescroller, can be referenced later by setTimeout (which works exclusively with global references).The setTimeout and setInterval functions execute strings containing Program code in global scope, but a string would only be used above in older browsers that don't support function object references as arguments to these functions. In that case, they would call the toString method of the function object and attempt to execute it, which wouldn't be particularly useful without effort on the part of the author to replace the toString method.

As it is, the function expression above would form a closure, thereby retaining access to the local variables of the enclosing function expression.

The FAQ notes for the comp.lang.javascript newsgroup discusses the issues surrounding the use of function object references and setTimeout/setInterval (http://www.jibbering.com/faq/faq_notes/misc.html#mtSetTI).

Mike

bcswebstudio
04-27-2006, 04:33 PM
Thanks for the great info and link. I enjoyed the extra read on string vs. function reference. To learn more, here's the article mike referenced on closure (using the function(){..} construct as a parameter to setTimeout) (http://jibbering.com/faq/faq_notes/closures.html).

(google rich posting provided for the next javascript journeyman on a quest) ;)

A super simple example of this in action is below:


<html>
<script>
function fun1() {
var localvar = "This is a string in a local variable that would otherwise not be accessible by setTimeout!";
setTimeout(function(){alert(localvar)}, 1000);
}
</script>

<body onload="fun1();">
</body>
</html>