PDA

View Full Version : Passing Variables Function to Function



jscheuer1
03-25-2005, 08:04 AM
Here's one that has bothered me for some time, the answer is probably simple yet, so far has eluded me. When I write code and want to pass the arguments from one function to another I often, if not always have to do something like this (example from some code I'm working on, it works but, looks sloppy):


<script type="text/JavaScript"><!--
i=100;
function moz_switch(arg1,arg2){
x=arg1;// why are these two declarations necessary?
y=arg2;
fade=setInterval("moz_fade(x,y)",90);
}
function moz_fade(img1,img2){
document.getElementById(img1).style.MozOpacity=i/100;
document.getElementById(img2).style.MozOpacity=Math.abs(i/100-1)
i=(i-1);
if (i==0){
clearInterval(fade);
i=100;
}
}
//-->
</script>Notice the comment. If I pass arg1 and arg2 directly to the moz_fade function, I get an error like img1 is not defined or has no properties. Using the above code, it works. There must be a better way.

mwinter
03-25-2005, 10:51 AM
Here's one that has bothered me for some time, the answer is probably simple yet, so far has eluded me.I did touch on the subject in the closures thread (http://www.dynamicdrive.com/forums/showpost.php?p=6711&postcount=4). The problem is specific to the string argument version of setTimeout/setInterval.


<!--Stop including that. Seriously. It has absolutely no value any more and just perpetuates the myth of its necessity.


function moz_switch(arg1,arg2){
x=arg1;// why are these two declarations necessary?
y=arg2;
fade=setInterval("moz_fade(x,y)",90);
}When setInterval evaluates the string argument, it does it in the only sensible scope it can: global. Clearly, arg1 and arg2 don't exist at that level so you need to provide a globally accessible pair of variables.

Note the phrase "globally accessible". The variables in question don't need to be global themselves, but they have to be reachable in some way, whether it be through a series of member accessors, or through function calls.

An alternative is to use a closure:


var i = 100,
fadeTimer;

function mozSwitch(a, b) {
function fade() {
/* The images collection is the preferred way to access
* images. The images can be identified by either their
* id or name attributes (id takes precedence).
*/
document.images[a].style.MozOpacity = i / 100;
/* Wouldn't (1 - i / 100) (without the
* Math.abs call) achieve the same thing?
*/
document.images[b].style.MozOpacity = Math.abs(i / 100 - 1);
if(!--i) {
clearInterval(fadeTimer);
i = 100;
}
}
fadeTimer = setInterval(fade, 90);
}However, the caveat I mentioned in the closures thread applies.

Mike

jscheuer1
03-25-2005, 11:02 PM
Thanks Mike, I'm too busy to go over all that now but, will get back to you if I have any questions. I did take a quick look through and it seems like what I am looking for. I did understand the explanation of why I had to resort to what I did, as I had a feeling it was something like that but, didn't quite 'get it'. Again, thanks for taking the time.

mwinter
03-26-2005, 12:22 AM
Reading through the code I posted, I realised that no globals are necessary. Probably wasn't considering the code properly first time around...


function mozSwitch(a, b) {
var i = 100,
timer = setInterval(fade, 90);

function fade() {
document.images[a].style.MozOpacity = i / 100;
document.images[b].style.MozOpacity = 1 - (i / 100);
/* As the i local will be initialised to 100 every time
* mozSwitch is called, there's no need to reset it's value below.
*/
if(!--i) {clearInterval(timer);}
}
}Mike