I am binding a single click event to a large container using jquery (event delegation).
I have many different items within that container that are clickable.
The problem I am dealing with is that if I have 20 clickable items, I need to do a if else block x 20 in the container on click handler. Is there a way to make this cleaner? E.g:
attachClickEvent:function(){
$(".container").click($.proxy(this.handleOnClick,this));
},
handleOnClick:function(event){
var $target = $(event.target);
if($target.closest(".widget1").length >0){
//handle widget 1 interaction
}else if($target.closest(".widget2").length >0){
//handle widget 2 interaction
}else if($target.closest(".widget3").length >0){
//handle widget 3 interaction
}else if($target.closest(".widget4").length >0){
//handle widget 4 interaction
}else if($target.closest(".widget5").length >0){
//handle widget 5 interaction
}
}
etc.
Event Delegation is basically a pattern to handle events efficiently. Instead of adding an event listener to each and every similar element, we can add an event listener to a parent element and call an event on a particular target using the . target property of the event object.
The delegate() method attaches one or more event handlers for specified elements that are children of selected elements, and specifies a function to run when the events occur. Event handlers attached using the delegate() method will work for both current and FUTURE elements (like a new element created by a script).
First thing that comes to mind is using a loop:
var handlers = {
"widget1": function(event, candidate){},
"widget2": function(event, candidate){}
}
$.each(handlers, function(cssClass,handler){
var sel = '.'+cssClass;
var candidate = target.closest(sel);
if(candidate.length > 0) {
handler(event, candidate);
break;
}
});
Create Object With Functions
A little late to the game with this, but you should consider organizing your code like this.
If you have 20 unique actions for your widgets, you're going to all that code. Try to reuse common code by creating functions. Make a structure like this:
var actions = {
'widget1' : function(event) {
// handle widget 1 interaction
},
'widget2' : function(event) {
// handle widget 2 interaction
},
'widget3' : function(event) {
// handle widget 3 interaction
},
call : function(event) {
var prefix = "widget",
widget = $(event.target).closest('[class^="'+prefix+'"]'),
classN;
if(widget.length) {
classN = widget.attr('class').replace(new RegExp('.*('+prefix+'\\d*).*$'), '$1');
if(classN in this) {
this[classN](event);
}
}
}
};
Simplified Execution
Then, from your click handler, simply call the function like this:
handleOnClick : function(event) {
actions.call(event)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With