Trouble Passing Variables to Function (Called by setTimeout)
Okay so I am having the following problem. I have gotten AJAX to work and am trying to get Javascript to fade out an old review score and fade in with a new score. The important part right now is that when I try to run it I get the following error:
Code:
Uncaught ReferenceError: preciseResponseAverage is not defined
(anonymous function)
The following is my current code:
Code:
function starSubmitFxn(starNumber) {
function fadeIn(average, color){
'use strict';
var ratingAverage = document.getElementById('rating_average');
ratingAverage.innerHTML = (average);
//now time to change the ratings color
var entityRating = document.getElementById('rating');
entityRating.style.color = color;
window.color = color;
}
'use strict';
window.fade('rating');
//setTimeout("fade('rating')", 1000);
var ajax = getXMLHttpRequestObject();
if (ajax) {
var currentUsername = '<?php echo $current_username; ?>';
var currentEntityId = <?php echo $entity_id; ?>;
// Create the Ajax object:
ajax.onreadystatechange = function () {
if (ajax.readyState === 4) {
//Check the status code:
if ( (ajax.status >= 200 && ajax.status < 300) || (ajax.status === 304) ) {
//document.getElementById('ajax_status').innerHTML = ajax.responseText;
var starResponse = JSON.parse(ajax.responseText);
var starResponseNumber = parseInt(starResponse["1"].value);
var starResponseAverage = (parseInt(starResponse["1"].average));
var preciseResponseAverage = starResponseAverage.toPrecision(2);
var starResponseColor = starResponse["1"].newColor;
//var ratingDiv = document.getElementById('rating');
U.removeEvent(U.$('star_rating_div'), 'mouseout', function(){ newStarRating("<? echo $current_user_review_rows['review_score'] ?>", 'blue'); } );
U.addEvent(U.$('star_rating_div'), 'mouseout', function(){ newStarRating(starResponseNumber, 'blue'); } );
if (!isNaN(starResponseNumber)) {
//newStarRating(ratingNumber, "blue");//end of newStarRating call
var i = null;
for (i = 1; i <= 10; i++) {
document.getElementById('rating_star_' + i).src = '../images/white_star_17px.png';
} //end of star color reset
var j = null;
for (j = 1; j <= starResponseNumber; j++) {
document.getElementById('rating_star_' + j).src = '../images/blue_star_17px.png';
}
} //end of response text check
if(!isNaN(preciseResponseAverage)) { //if a number is returned, time to fade out / in
setTimeout("fadeBackIn(preciseResponseAverage, starResponseColor)", 400);
}
} //end of Ajax connectivity check
else { //if Ajax status text is a failure
}
} //end of Ajax ready state
}; //end of function for execution on ready state change
var data = 'currentUsername=' + encodeURIComponent(currentUsername) + '¤tEntityId=' + encodeURIComponent(currentEntityId) + '&starNumber=' + encodeURIComponent(starNumber);
ajax.open('POST', '../resources/star_submit.php?' + data, true);
ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
ajax.send(data);
} //end if ajax object exists
else {
} //end if it doesn't exist
} //end of starSubmitFxn
There are some functions defined outside of this function but I don't think those are necessary for me to post right now. The issue seems to be that I'm not sure how to properly send a variable to a function when that function is called via setTimeout. Any help would be appreciated. Thank you.
setTimeout expects a function as the first parameter so the string you supply is effectively being wrapped in an anonymous function that is run after the specified time.
The preciseResponseAverage variable is only defined in the anonymous function attached to the onreadystatechange event handler and so that copy has gone out of scope by the time that your string gets converted into a function.
Converting it to a function yourself so that the fields it references are visible before they go out of scope will hopefully create the needed closure.
Yeah I decided the best way to do it was to modify and use a setTimeout function within a for loop. For some reason it seems like it is not going through the loop correctly though. Here is the relevant part of my code:
Code:
function fade(currentTime, newAverage, newColor) {
if (currentTime <= 5){
var currentOpacity = 1.0 - (currentTime * .2);
document.getElementById('rating').style.opacity = currentOpacity;
document.getElementById('logo').style.width = "500";
}
if(currentTime >= 5){
var ratingAverage = document.getElementById('rating_average');
ratingAverage.innerHTML = (newAverage);
//now time to change the ratings color
var entityRating = document.getElementById('rating');
entityRating.style.color = newColor;
var currentOpacity = currentTime * 2 - 1.0;
document.getElementById('rating').style.opacity = currentOpacity;
}
}
document.getElementById('rating').style.opacity = 1.0;
for (var timer = 0; timer < 10; timer++){
setTimeout(function(){fade(timer, preciseResponseAverage, starResponseColor)}, 100);
}
I was hoping for a slow fade but am not getting that. Currently it's not even changing the opacity at all when I click on it, nor the color of the text. In fact I added the logo.style.width = 500 line specifically to test to see whether it's even looping at all and it appears that it's not because the logo on the page is not changing to 500px (whether I include the 'px' or not). It's will change the actual rating itself though...
Edit: Heck I even got it to change the color but when it changes there is no opacity fade at all. It's like Javascript is only executing the final part of the loop or something...
That code is saying "Repeat 10 times: 100 milliseconds from *RIGHT NOW* call the fade function."
It is *NOT* saying "call the fade function 10 times, each time 100 milliseconds after the last".
So all 10 calls to fade( ) are being made...but they are *ALL* being made at essentially the same time.
So the human eye only sees the result of the last call.
You see that?
The first call to fade will be at 100*(0+1) milliseconds.
The second call to fade will be at 100*(1+1) milliseconds.
...
The 10th call to fade will be at 100*(1+9) milliseconds, or 1 full second later.
Is this the best way to do it? Probably not. But it's workable.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Last edited by Old Pedant; 01-24-2013 at 07:29 AM..
And, yes, you *MUST* specify "px" when changing a style property if you want the number to be interpreted as pixels. MSIE will default to pixels, but other browsers will just ingore the number. Remember, you can use "pt" and "%" and a few other things other than "px", so the browser insists you tell it which.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.