The old event management in which each handler for specific actions was directly attached to the target element is becoming outdated, since considerations about performance and memory saving started spreading in the developers community.
Event delegation implementations had an acceleration since jQuery updated the old fashioned .bind()
and .live()
methods with the new .on()
method to allow delegation.
This determines a change in some seasoned approaches, where to use event delegation a rework is necessary. I am trying to work out some best practice while keeping the coding style of my library, and looked for similar situations faced from other developers to find an answer.
Using OOP with functions as constructors, I usually have interfaces for objects creation like this:
var widget = new Widget({
timeout: 800,
expander: '.expanders'
});
with object literals given as argument, providing a clean map of names and values of the input passed. The class underlying this code could be something like the following:
var Widget = function(options) {
// some private members
var _timeout;
var _$widget;
var _$expander;
// methods
this.init = function() {
_timeout = options.timeout || 500;
_$expander = $(options.expander);
_$widget = _$expander.next();
_$expander.on('click', _toggle);
};
var _toggle = function(e) {
if (_$widget.is(':visible')) {
_$widget.hide(_timeout);
} else {
_$widget.show(_timeout);
}
};
this.init();
};
Using "private" methods gave me some benefits in terms of code readability and cleanness (only useful methods are publicly exposed to the user), beyond the small gain in performance (each scope resolution takes more time than a local variable). But when speaking about event handlers, it clashes with the event delegation paradigm.
I thought to make public the methods that I used to associate internally to the listeners in the class:
this.toggle = function(e) {
if (_$widget.is(':visible')) {
_$widget.hide(_timeout);
} else {
_$widget.show(_timeout);
}
};
then driving externally, or in another proxy class, the proper delegation with something like this:
var widget = new Widget({
expander: '.expanders'
});
$(delegationContext).on('click', '.expanders', widget.toggle);
but it did not seem to me the best approach, failing in the exposure of a non-useful method in the interface, so I tried a way to let the main class know directly all the information to delegate the event autonomously, through the interface:
var widget = new Widget({
timeout: 800,
expander: {
delegationContext: '.widgetContainer',
selector: '.expanders'
}
});
which would allow to keep on using private methods internally in the class:
var $context = $(options.expander.delegationContext);
$context.on('click', options.expander.selector, _toggle);
What are your practice and suggestions about it?
And what are the main trends of other developers you heard about as far as today?