jQuery's bind() method is extremely useful. If you call $(myElement).bind('change',function(){...}) multiple times, you can chain multiple events on the same element.
$('a').bind("click", function() { alert('event 1'); });
$('a').bind("click", function() { alert('event 2'); });
These two calls will take all links on in your DOM and alert("event 1") and alert("event 2") when any of them are clicked. Fantastic!
However, there is the potential for an undesired side effect if you use bind unwisely. For example, say you have a modal dialog popup in your application. When you have to display the modal dialog, you perform some setup first:
1: function SetupModalDialog() {
2: $('select', '#dialogContainer').bind('change',function(){
3: alert('be careful what you wish for');
4: });
5: }
If for some reason you have to call SetupModalDialog multiple times (perhaps because some of the controls are dynamic based on other parts of the page), the drop downs will have this function bound to the change event each time this function is called. What does this mean? If you open your dialog twice, and change the selection on a dropdown in the dialog, you will see two alert windows saying "be careful what you wish for".
There are a couple of ways you can handle this situation. One would be to go back through the elements you've setup events on and call unbind. Having clean up code like this is ideal, but not always practical. Another solution which will minimize your code changes is to make sure you're not binding the same function more than once.
Introducing bindOnce
1: function bindOnce(element, event, handler) {
2: if (element === undefined || event === undefined || handler === undefined)
3: return;
4:
5: var jqueryObj = $(element);
6:
7: var events = jqueryObj.data('events');
8:
9: if (events === undefined) {
10: jqueryObj.bind(event, handler);
11: }
12: else {
13: if (events[event] === undefined) {
14: jqueryObj.bind(event, handler);
15: }
16: else {
17: var isBound = false;
18: $.each(events[event], function(i, eventHandler) {
19: if (eventHandler.toString() === handler.toString()) {
20: isBound = true;
21: return false;
22: }
23: });
24:
25: if (isBound === false) {
26: jqueryObj.bind(event, handler);
27: }
28: }
29: }
30: }
bindOnce simply excepts and element, the event to handle ('click'), and the function to handle the event. By using the jQuery.data("events") collection, we can determine if the event and function have already been bound to the element in question.
Of course what good reason is there to have a method to do the work that does not extend jQuery? None that I can think of, so here's the jQuery plugin:
(function($) {
$.fn.bindOnce = function(event, handler) {
if (event === undefined || handler === undefined)
return;
var events = this.data('events');
if (events === undefined) {
this.bind(event, handler);
}
else {
if (events[event] === undefined) {
this.bind(event, handler);
}
else {
var isBound = false;
$.each(events[event], function(i, eventHandler) {
if (eventHandler.toString() === handler.toString()) {
isBound = true;
return false;
}
});
if (isBound === false) {
this.bind(event, handler);
}
}
}
};
})(jQuery);
The usage is typical:
1: $('a').bindOnce('click', function() { alert('Hey...'); });
Enjoy.
3a2e130b-a23f-4e2b-8576-568d52793aa4|0|.0