I created a class called SearchBox to handle search interaction (delayed trigger, search on enter key press, preventing searches while one is active, synchronizing results when a search completes and the text has changed, etc.).
All the class methods are prototype methods, meant to be accessed via this
. In the following code, assume p
is the class's prototype.
p.registerListeners = function () {
$(this.element).on('keypress', this.searchKeyPressed);
};
p.unregisterListeners = function () {
$(this.element).off('keypress', this.searchKeyPressed);
};
That doesn't work, because when the keypress event calls the searchKeyPressed
handler, it doesn't do so in the context of this
. The only solution I can come up with is one that only modern browsers support, which is to bind the callback to this
, which actually creates a new function. Since it creates a new function, I have to cache it in order to remove it later, since I have to pass the same reference to off
that I passed to on
.
Is there a better way to do it than this, or is this ok?
var boundKeyPressed;
p.registerListeners = function () {
boundKeyPressed = this.searchKeyPressed.bind(this);
$(this.element).on('keypress', boundKeyPressed);
};
p.unregisterListeners = function () {
$(this.element).off('keypress', boundKeyPressed);
};
I thought that maybe jQuery.on
would provide a way to do this event binding automatically, but instead it seems like it binds this
to different things depending on how it's called. For example, when using on('eventname',instance.func)
, this
is the "currentTarget" (not necessarily "target" in bubbling terms), whereas when using on('eventname','selector',instance.func)
, this
refers to the element matching the selector. In either case, the func
runs as though it has no relationship with instance
.
If you add a namespace to your events you can bind events and easily unbind them all at once.
To bind:
$(this.element).on('keypress.mynamespace', this.searchKeyPressed.bind(this));
To unbind:
$(this.element).off('.mynamespace');