Reputation: 5662
I want to create a Jquery UI widget that starts an interval on creation. The function called on each interval timeout is supposed to be overrideable and therefore placed in the options
object.
I can start the interval from outside the widget, and I can call the overrideable function from outside the widget. But when the interval tries to call the overrideable function, it's undefined
.
Here is my widget:
jQuery.widget("awesome.me", {
options: {
verbose:false, // just some setting
onTimeOut: function(){ // this is the function that is called by the timeout and that should be overrideable
console.log("on timeOut called");
}
},
_create: function(){
console.log(this.options); // logging the options object
},
_members: { // a private object to hold internal settings and stuff, for example the interval instance
interval: null
},
start: function(){
this._members.interval = setInterval(this.doIt, 2000);
},
stop: function(){
clearInterval(this._members.interval);
},
doIt: function(){
console.log(this.options); // here I would like to call my onTimeOut function, but the options are undefined, because THIS is undefined
}
});
From the outside, in the script I do this to instantiate my widget and start the interval:
$(document).me(); // I am not overriding the function for now
var widget = $(document).data("awesome-me"); // to facilitate access to my widget I grab the instance and put it in a normal variable
widget.start(); // start() will set the interval
If I where to call widget.doIt()
, the console would show something like this:
Object {classes: Object, disabled: false, create: null, verbose: false}
But when I run the script, every two seconds this appears:
undefined
So from my understanding, when I call widget.start()
, the interval will start calling this.doIt
every 2 seconds, but inside the doIt
function, when it tries to log the options
object, it is gone. So my widget
variable still has the correct instance of my widget and I can call every function I want. But when the interval times out, it holds some other widget instance where the function doIt
exists, but this
is undefined.
What I don't understand is: why? How I can fix this?
Upvotes: 2
Views: 196
Reputation: 25726
The problem is with this._members.interval = setInterval(this.doIt, 2000);
When this.doIt
is called, it is called with this
being window
, which in turn is really, window.options
which is being accessed in doIt
(do console.log(this)
to see what it is inside of doIt
when it is ran).
The fix is to bind or execute doIt
passing this
.
this._members.interval = setInterval(this.doIt.bind(this), 2000);
or
var self = this;
this._members.interval = setInterval(function(){self.doIt();}, 2000);
Upvotes: 2