Hi everybody.
This is not so much a problem, since I have already managed to find a solution, but my solution requires the use of the eval() function, which I just hate to use.
The problem is this.
I have an object that has a function. This function needs to call itself in a setTimeout call. Using the "this" keyword from within the callback function will obviously not work, seeing as it would reference the new function rather than the object instance.
So, in an attempt to solve that, I create a reference to "this" before I create the callback function and use that inside the callback function, like so:
[code=javascript]
// Minimized the code to get to the point
function Updater(pTarget Element, pMaxValue)
{
this.update = function(pCurre nt)
{
self = this;
window.setTimeo ut(function(){
self.update(pCu rrent);
}, 50);
}
}
[/code]
And this works... almost.
The object is meant to manipulate an element, taking an initial value and counting up until the max value is reached, displaying the current value in the given target element.
And this does exactly that... if I have only one instance of the object running at a time.
Once a second instance is in play, the two will be fighting over the "self" variable, which is apparently created in a scope that both instances use.
As a result, if a first instance sets the "self" value to itself and fires of the setTimeout, a second instance may be called before the timeout is reached, altering the "self" variable, which is then reflected in the timeout calls from both objects.
This effectively doubles the effect on the second instance, while the first instance is left unchanged.
And this is my problem. How do I create the "self" variable in a scope that is unique to each object instance? So when the second instance is called, it will not alter the variable created by the first instance.
But, like I said, I managed to find a solution by using the eval() function.
My thinking was that the main problem is the second instance re-using the same variable. So I created a "dynamic" variable by creating a random number and turning that into a variable by running it through the eval function.
Like so:
[code=javascript]
function Updater(pTarget Element, pMaxValue)
{
this.update = function(pCurre nt)
{
rand = Math.floor(Math .random() * 10000);
eval("self_" + rand + " = this;\
window.setTimeo ut(function(){\
self_" + rand + ".update(" + pCurrent + ");\
}, 50);");
}
}
[/code]
This is obviously flawed. Even tho it is a pretty safe method, there is always a chance that the random numbers collide causing a problem, not to mention that this will create a bunch of random variables that are left lying around.
This can be used, and my use of it will be limited so the potential of problems is minimal, but there just has to be a better way.
This is the full code I am using to test this, just in case:
[code=javascript]
function Updater(pTarget Element, pMaxValue){
this.targetElem ent = pTargetElement;
this.maxValue = pMaxValue;
this.update = function(pCurre nt){
if (pCurrent >= this.maxValue) {
return;
}
++pCurrent;
this.targetElem ent.innerHTML = pCurrent.toStri ng();
rand = Math.floor(Math .random() * 10000);
eval("self_" + rand + " = this;\
window.setTimeo ut(function(){\
self_" + rand + ".update(" + pCurrent + ");\
}, 50);");
}
}
function bodyOnLoad(){
for (i = 1; i <= 3; i++) {
eval("window.se tTimeout(functi on(){\
updater = new Updater(documen t.getElementByI d(\"Counter" + i.toString() + "\"), 50);\
updater.update( 0);\
}, (250 * " + i.toString() + "));");
}
}
[/code]
This uses three "CounterX" <div> elements as containers, each of them counting up to 50, one starting 250ms after the other.
And (shockingly) this work in all my browsers except IE.
Any input would be greatly appreciated.
Thanks,
- Atli Þór
This is not so much a problem, since I have already managed to find a solution, but my solution requires the use of the eval() function, which I just hate to use.
The problem is this.
I have an object that has a function. This function needs to call itself in a setTimeout call. Using the "this" keyword from within the callback function will obviously not work, seeing as it would reference the new function rather than the object instance.
So, in an attempt to solve that, I create a reference to "this" before I create the callback function and use that inside the callback function, like so:
[code=javascript]
// Minimized the code to get to the point
function Updater(pTarget Element, pMaxValue)
{
this.update = function(pCurre nt)
{
self = this;
window.setTimeo ut(function(){
self.update(pCu rrent);
}, 50);
}
}
[/code]
And this works... almost.
The object is meant to manipulate an element, taking an initial value and counting up until the max value is reached, displaying the current value in the given target element.
And this does exactly that... if I have only one instance of the object running at a time.
Once a second instance is in play, the two will be fighting over the "self" variable, which is apparently created in a scope that both instances use.
As a result, if a first instance sets the "self" value to itself and fires of the setTimeout, a second instance may be called before the timeout is reached, altering the "self" variable, which is then reflected in the timeout calls from both objects.
This effectively doubles the effect on the second instance, while the first instance is left unchanged.
And this is my problem. How do I create the "self" variable in a scope that is unique to each object instance? So when the second instance is called, it will not alter the variable created by the first instance.
But, like I said, I managed to find a solution by using the eval() function.
My thinking was that the main problem is the second instance re-using the same variable. So I created a "dynamic" variable by creating a random number and turning that into a variable by running it through the eval function.
Like so:
[code=javascript]
function Updater(pTarget Element, pMaxValue)
{
this.update = function(pCurre nt)
{
rand = Math.floor(Math .random() * 10000);
eval("self_" + rand + " = this;\
window.setTimeo ut(function(){\
self_" + rand + ".update(" + pCurrent + ");\
}, 50);");
}
}
[/code]
This is obviously flawed. Even tho it is a pretty safe method, there is always a chance that the random numbers collide causing a problem, not to mention that this will create a bunch of random variables that are left lying around.
This can be used, and my use of it will be limited so the potential of problems is minimal, but there just has to be a better way.
This is the full code I am using to test this, just in case:
[code=javascript]
function Updater(pTarget Element, pMaxValue){
this.targetElem ent = pTargetElement;
this.maxValue = pMaxValue;
this.update = function(pCurre nt){
if (pCurrent >= this.maxValue) {
return;
}
++pCurrent;
this.targetElem ent.innerHTML = pCurrent.toStri ng();
rand = Math.floor(Math .random() * 10000);
eval("self_" + rand + " = this;\
window.setTimeo ut(function(){\
self_" + rand + ".update(" + pCurrent + ");\
}, 50);");
}
}
function bodyOnLoad(){
for (i = 1; i <= 3; i++) {
eval("window.se tTimeout(functi on(){\
updater = new Updater(documen t.getElementByI d(\"Counter" + i.toString() + "\"), 50);\
updater.update( 0);\
}, (250 * " + i.toString() + "));");
}
}
[/code]
This uses three "CounterX" <div> elements as containers, each of them counting up to 50, one starting 250ms after the other.
And (shockingly) this work in all my browsers except IE.
Any input would be greatly appreciated.
Thanks,
- Atli Þór
Comment