JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Here's one I've been struggling with for a bit now. I need to make a setTimeout() call to a method or function inside of a class and pass a parameter. Say I'm in a method and inside of that method I need to fire a request to do delayed execution of another method in the same class.
Outside of classes you can do this:
if (Timeout && Timeout > 0)
window.setTimeout("HideToolTip('" + ControlId + "')",Timeout);
This works fine with plain global functions. But now imagine you have a method in a class:
this.ShowToolTip = function (Message,Timeout,Position)
{
…
if (Timeout && Timeout > 0)
window.setTimeout("this.HideToolTip('" + ControlId + "')",Timeout);
}
this.HideToolTip = function(ControlId)
{
… do something with ControlId
}
Now how do you set up the call for window.setTimeout()? Hint: The above doesn't work <s>. The reason is that window.setTimeout doesn't call from within the context of the class so 'this' is not in scope – and the call fails. Same applies if you don't make HideToolTip a class method but plain function inside of the class – it still won't be visible to the window object and setTimeout.
Calling the method is really not that big of a problem. Instead of a string you can pass in an event handler object reference, so you can do this:
if (Timeout && Timeout > 0)
window.setTimeout(this.HideToolTip,Timeout);
That works in firing the method or function, but there's unfortunately no way to pass a parameter. Well, officially there may be.
Incidentally I was browsing through my JavaScript Bible that mentioned this working:
window.setTimeout(this.HideToolTip,Timeout,ControlId);
and it actually works in FireFox, but unfortunately not in InternetExplorer. Looking online though I don't see this syntax referenced in any of the browser references. So that's out… Too bad cause that would have been easy.
What about calling the class method and letting class properties deal with 'passing' of values? So instead of trying to pass a ControlId why not set a property on the object or use some property, something like this (using ATLAS for that matter):
this._hideToolTip = function (ControlId)
{
var ControlId = $(this.element.id);
var Ctl = $(ControlId + "_ToolTip");
if (Ctl == null)
return;
Ctl.style.display="none";
Ctl = $(ControlId + "_ToolTipShadow").style.display="none";
}
Seem logical OO – but nope that doesn't work. When the setTimeout call is made this, doesn't refer to your object, but to the window object. Grrr… so much for object orientation in JavaScript.
So what's the answer here? Actually I've been looking at how ATLAS does this, but I can't for the life of me get ATLAS events using eventArguments to fire for me either. The events get hooked up but they just never actually trigger the handlers.
So anybody have any ideas on to make call another method in a class with the proper context?
The Voices of Reason
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
<html>
<body>
<script>
function MyClass() {
}
MyClass.prototype.setTimer = function(msg) {
var myClass = this;
function timerRelay() {
myClass.handleTimer(msg);
}
alert("Starting timer");
setTimeout(timerRelay, 1000);
}
MyClass.prototype.handleTimer = function(msg) {
alert(msg);
}
var c = new MyClass();
c.setTimer("Hello");
</script>
</body>
</html>
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
var cbk = Function.createCallback(myFunction, myParameter);
window.setTimeout(cbk, 1000);
The cbk function will remember the context parameter for the function.
Also take a look at Function.createDelegate.
Does this help?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
var self = this;
setTimeout(function(){
self.HideToolTip(ControlId);
}, 200);
Using this can be tricky, safer to tuck it into a variable then reference the variable to avoid any weird scope issues.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
The solution is simply not to create a 'property' but to create a variable within the 'class' function scope.
Sys.UI.ToolTip = function(associatedElement)
{
var _controlId = associatedElement.id;
this.function Fire() {
window.setTimeout(this.DoSomeThing,300)
}
this.function DoSomeThing()
{
alert( _controlId );
}
}
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
I was actually facing the similar trouble and was browsing through the web. Also read through your article and responses. But did not get any clue.
However, Finally I was able to solve my problem. Lets see if it is the same as yours.
Basically we are using ASP.NET 2.0 script callback feature. Now after making the call to server there is a function on the client that will handle the returned results. However, while client callback funciton handles the results, I also wanted to schedule call to other client functions based on which client control started the script-callback originally.
Therefore when I initially make a server call I pass it a client function to be called when it comes back e.g. "myfunction". script-callback function on the client handles the result and retrieves the name of the function from the returned XML results. After this it concatenates the function name with the "(arguments)" so that function call becomes something like "myfunction(arguments)". Now I create a anonymous function wrapping the original function call and assign it to one of the properties of an existing stub function created just for this purpose. Also assign the controlID to be passed to another property of stub function. Now schedule the call to stub funciton using setTimeout. within the stub function you call the its property to which we assigned the anonymous function passing it the value assigned to another property of the same stub function.
This solved my problem.
function myStubFunction()
{
myStubFunction.CallMyFunction(myStubFunction.Param1, myStubFunction.Param2);
}
function ProcessCallBackResult (args, context)
{
//Suppose I retrieve this value from the callback result.
var myCall = "myfunction";
myCall += "(arguments)";
myStubFunction.CallMyFunction = new Function('controlID', 'msg', myCall);
myStubFunction.Param1 = targetControlID;
myStubFunction.Param2 = "This is example of passing multiple arguments";
window.setTimeout("myStubFunction();", 1000);
}
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Just forgot to mention that in the last code I posted, in my fuinal function i.e. "myfunction" I retrieve the values of controlID or any other parameter using "arguments" array. e.g.
controlID = arguments[0];
msg = arguments[1];
and so on....
Thanks
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Give my ToolPanel control a look:
http://www.angrypets.com/tools/toolpanel/
(just look at the source on that page). I grab a handle to a div/element in there, and then pass it to a method which is called by setTimeout.
It was a booger to set up, and the end result is that it required the use of 'ticks' inside.
case in point:
var sMsg = "Hello, world";
window.setTimeout("alert(" + sMsg + ")", 1000);
won't work, but
var sMsg = "Hello, world";
window.setTimeout("alert('" + sMsg + "')", 1000);
will work - cuz I've added ticks in there to wrap my text.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
var myTimeout=Class.create();
myTimeout.prototype={
initialize:function(message,timeOut){
this.message = message;
this.timerID = window.setTimeout(this.showMessage.bind(this), timeOut);
},
showMessage(){
alert(this.message);
}
}
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Yahoo use "apply" in their YUI/connection/connection.js library.
There's also reference to it here:
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function:apply
Yahoo seem to use it to change scope, but it also allows arguments to be passed to the function.
eg,
window.setTimeout (function () { myObject.myFunction.apply (myObject, [arg1, arg2, arg3]); }, 1000);
And suppose you need/want to "restart" your current function in (say) 1 second...
function doSomething(arg1, arg2)
{
if (!ready)
{
// try back later
var myContext = this;
window.setTimeout (function () { myContext.doSomething.apply (myContext, [arg1, arg2]); }, 1000);
return;
}
// finish the job
}
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
The following works to keeps the parameters in context for a function call:
window.setTimeout( function() { Fadeout.call(this, ControlId,HideOnZero,Step,Percent, UseVisibility); },30);
where this is the current call context or function.
I don't quite understand how it works in keeping the context, but it does <g>...
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
If you want two running at the same, this hasn't worked for me. I'm still working on it and I'll leave a response if I get it working
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Then when it comes to generating the string for the call back, you do something like:
window.setTimeout(this.name+".method("+param1+", "+param2+")", 10);
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
researching about the same issue, I came accross this 'asynchronous call wrapper'. This should do the trick ? Going to try it right away !
http://devedge-temp.mozilla.org/toolbox/examples/2003/CCallWrapper/index_en.html
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
The real solution to the problem I brought up here is to use function.apply or function.call to preserve the call context, but this is neither obvious nor intuitive to write. Having to make calls with .apply and .call just to preserve functional state is a pain in the ass and if you come from a background in 'real' OO it smells of procedural programming.
It's taken me a heck of a lot of time to get a basic grasp of some of these concepts - they are not logical and certainly not easy to pick up. For one there are so many different ways that you can 'fake' OO classes and class like behavior all with various differing behaviors for the class implementation. It sucks...
I don't consider myself particularily dense when it comes to different concepts, but this has been one that just goes counter my intuition which makes it difficult at best. I suspect it's the same for many other developers using typed or even more traditional dynamic/interpreted languages.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
var _this = this;
this.Timerid = setTimeout(function(){_this.handleError('var in here');},this.httpTimeOut);
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
function delegate_withparameter(object, thatMethod){
if(arguments.length > 2)
{
var _params = [];
for(var i = 2; i <arguments.length; i++){
_params.push(arguments[i]);
}
return thatMethod.apply(object, _params);
}
else
return thatMethod.call(object);
}
so for timer problem:
window.setTimeout( delegate_withparameter(this,this.HideToolTip, controlId),Timeout);
would do..
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
If I had only learned JavaScript before ActionScript, I would be ignorant to the potential for sensible scope.
PS. If, for some reason, you decide to look at my site, please bare in mind it hasn't been updated in 2 years. This fact amuses me, given I'm attempting to write a GUI for firefox/IE at my place of employment and yet... old personal site.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
The solution of Rick Strahl (the call method) works, but only when I do NOT put the call statement in an anonymous function like this:
this.oInterval = window.setInterval(this.__interval.call(this), 1000);
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
this.Timerid = setTimeout(function(){_this.handleError('var in here');},this.httpTimeOut);
Yes, it works, but memory leaks like hell ;[ Because everytime the line var _this=this; is executed, a new copy of the object is created.
Forexample I want to create an Ajax class that also can repeat requests after some interval:
Ajax.prototype.get = function(method, url, func, id, timer) {
var request = this.createRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200)
switch (method) {
case "text":
func(request.responseText, id);
break;
case "xml":
func(request.responseXML.documentElement);
break;
}
}
request.open("GET", this._rndsid(url), true);
request.send(null);
if (timer) {
var _this = this;
setTimeout(function(){_this.get(method, url, func, id, timer);}, timer);
}
}
... the usage is something like this:
<div id = "d"></div>
....
ajax = new Ajax()
ajax.getFill("rnd.php", "d", 1000);
It sets the innerHTML of the div with id "d" to whatever content rnd.php returned every second. Yes, it works, but it memory leaks ;[ I can't afford that, because after a hour or so the browser will take most of the RAM and even start scratching like hell. How to destroy the "_this" instance after it s used?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
setTimeout(function(){object["method"].apply(object,[arg1,arg2,...])},1000); function Class() { this.method=method; } function method(arg1,arg2){//do sth with args} object = new Class();
anonymous function with redirection to another function within object scope
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
The passing this as a new variable doesn't work, and nor can I make any odds with the Function.apply method, which in essence still suffers from the same problem.
Has anyone actually got this working on IE?
thanks
Pete
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
window.setTimeout(function() { this.HideToolTip(ControlId) },Timeout);
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Example syntax:
monitorTimeout: function() {
window.setTimeout(this.checkTimeout.bind(this), 60000);
},
Good luck.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
The big problem with this approach is that you have to remember each time you call a method this way to do it with the right syntax, otherwise that code is bypassed.
FWIW, I'm still to date using a var _I (for Instance) in classes and reference the _I instead of this in code. That always works with no further configuration - it's just remembering to use _I instead of this <shrug>...
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
The closure things helped me a lot.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
this.param1 = "";
this.methodToCall = function() {
alert(this.param1);
}
this.method = function() {
setTimeout(
function(thisObj) { thisObj.methodToCall(); },
this.time,
this);
}
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
(1) The 'intended' method call (doesn't work):
setTimeout( this.HideToolTip, Timeout, ControlId );(2) Using call(), as above:
var myContext = this; setTimeout ( function () { myContext.HideToolTip.call( myContext, ControlId ); }, Timeout );
(3) Using nested functions:
setTimeout( ( function ( obj, param ) { return function () { obj.HideToolTip( param ); }; } )( this, ControlId ), Timeout );
It does just the same thing: currying the parameter value and the object into the scope.
* First, an inner function is created, calling obj.HideTooltip( param ) - whatever obj and param might be at that point.
* Next, an outer function is set up which allows you to specify obj and param. It returns the inner function with obj and param fixed. That's the whole point: obj and param will become part of the function's call stack as soon as the outer function is called. Afterwards, they will stay the same even if the scope has changed.
* Last step: The outer function *is* called, with 'this' and controlId as parameters. It manufactures a function where obj and param are frozen to their current values, and returns that function. You can call the result anytime and in any context, and it will do the right thing. E.g., you can pass it to setTimeout, which will execute it in the global context.
Using nested functions may look more complicated than call(), but perhaps it can help to make the process involved a little clearer.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
function DoSomething(myValue) { var callbackFunction = function() { // do stuff with the myValue parameter alert(myValue); } // Execute the function with time-out window.setTimeout(callbackFunction, 1000); }
For example to show a message with a delay:
DoSomething("Hello World");
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Thanks,
Hans
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
I am both calling the settimeout method from within my class, assigning the id to a class parameter and passing the current call object through to the target class method, setting my delay from a class global delay variable.
Like so
Inside my input handler (this is fired from keyup, keydown, paste and various other change events on the page)
//here is my class method thats pointed to by various bound methods this.qchng = function (e) { //assign my class wide Timer id "MS.sTid" to the new timer im creating //passing the object "e" through to class method I want to call "MS.aChange(e)" //once the given delay has elapsed "MS.gw" MS.sTid = window.setTimeout(function () { MS.aChange(e); }, MS.gw); };
Hope this helps those that might have been struggling with this.
Best Regards
Andre
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
function Timer(callback, milliseconds, context) { this.milliseconds = milliseconds; this.callback = callback; this.context = context; if (!this.context) this.context = this; this.handle = null; } Timer.prototype.start = function() { var timer = this; var context = this.context; var timeUp = function() { timer.callback(context); } this.handle = setTimeout(timeUp, this.interval); } Timer.prototype.stop = function() { clearTimeout(this.handle); }
Then, in a class of your choice, you can instantiate the timer, passing *this* as the context. The callback function will get a context parameter that is actually the object passed to the timer.
If you don't pass an object, the context will be the timer itself, so a different approach would be to not pass *this*. Set whatever data needed into the timer, and retreive that data through the context parameter of the handler, which will set to the timer at that time.
I think the first approach is more transparent:
MyObject.prototype.timeUp = function(context) { alert(context.whateverProperty); } MyObject.prototype.startRunning = function() { // Pass ourselves as the context of the timer. this.timer = new Timer(this.timeUp, 2000, this); this.whateverProperty = 'Test'; // Start the timer. this.timer.start(); }
You can ofcourse choose to start the timer directly from the constructor, but I figured it could be handy to be able to start later (especially if you choose the second approach and need to set properties to the timer too).
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
this.handle = setTimeout(timeUp, this.interval);
should ofcourse be
this.handle = setTimeout(timeUp, this.milliseconds);
I decided to rename interval to milliseconds, but forgot to alter this line.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Since firefox has some strange reaction sometimes you try to focus() on a text field, setTimeout might come in very handy:
var SingletonObj = { refocus: function(htmlref) { window.setTimeout(function() {htmlref.focus();},5); } };
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
First off all, I am happy to post a solution to Rick's blog which has helped me a few times now, since 2007. Thanks Rick!
My solution is simple and doesn't risk any race conditions by setting global data, etc.
The general problem is we have two methods, and the first once the second to be invoked after a timeout and with the control that is in-context passed as a parameter.
function FirstFunction() {
.. do some stuff
window.setTimeout("SecondFunction('" + $(this).attr('id') + "')", 50);
}
function SecondFunction(targetId) {
$('#'+target).css('background','#f00'); //set background red
var x = document.getElementById(target)
//do something with x
}
The key to this is how the call to SecondFunction is created. Notice that the whole function invoke is a string-literal. with single-quotes embedded just inside the parenthesis and surrounding the parameter's literal value. So it is a string-literal embedded inside of a string-literal! By way of example, if FirstFunction's in-context control has an id of "OfficerRank" then the line ends up looking like this:
window.setTimeout("SecondFunction('OfficerRank')", 50); //50 ms timeout
This has worked for me reliably in IE8, IE9, FireFox 8, Opera, Safari and Chrome.
Live Long and Prosper
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
Took some time to understand Jos Vissers comment, but finally, it's as easy as
var ref = this;
setInterval(function(){
ref.loop();
}, 200);
Thank you all!
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?
your code snippet helped me a lot.
# re: JavaScript window.SetTimeout to a JavaScript Class method or function with parameters?