Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Event Delegation code organization

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.

like image 645
Abadaba Avatar asked Apr 09 '11 04:04

Abadaba


People also ask

How does event delegation work in JavaScript?

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.

How do you delegate in JavaScript?

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).


2 Answers

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;
  }
});
like image 99
prodigitalson Avatar answered Sep 23 '22 04:09

prodigitalson


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)
}
like image 34
typeof Avatar answered Sep 23 '22 04:09

typeof