3

I'm a big fan of using jQuery's delegated event handling signature:

$('.container').on('click', '.button', function () {
  // do something
});

I'm also a big fan of using the multiple event handler signature:

$('.container').on({
  click: function () {
    // do something
  },
  mouseover: function () {
    // do something else
  }
});

I'm wondering whether there's a way to combine the two together. I want to be able to handle click events on multiple different descendants of the same root element.

My first guess was that I could pass a second argument to the handler functions, but an inspection of the arguments variable showed no additional data coming in besides the event object.

Is there a design pattern to accommodate this or do I just have to bite the bullet and continue doing this?

$('.container')
    .on('click', '.button-a', function () {
      // do something
    })
    .on('click', '.button-b', function () {
      // do another thing
    })
    .on('click', '.button-c', function () {
      // do yet another thing
    });
natlee75
  • 5,097
  • 3
  • 34
  • 39
  • I'm not exactly sure about this, but i think if you listen to the container only, and inspect the event object there is there is a target attribute, through which u could access what was clicked. – MikeWu Jun 04 '14 at 23:35
  • In case you're doing different things in the handlers for different selectors, I don't see anything wrong with this. – Bergi Jun 05 '14 at 02:34
  • I chain it with no noticeable performance degradation. – thdoan Jun 25 '20 at 23:30

3 Answers3

2

In this case you can separate with a ,.

Like this:

$('.container')
  .on('click', '.button-a, .button-b, .button-c', function () {
      // do something
  });

But this is because you are using the same event.

If you want to combine the multiple event signature, you can do it in this way:

$('.container .button-a, .container .button-b, .container .button-c').on({
  click: function () {
    // do something
  },
  mouseover: function () {
    // do something else
  }
});
Jacobi
  • 1,508
  • 15
  • 29
1

I would use the event Object to check for the element that was clicked on.

And based on the element that was clicked would execute the code block.

$('.container').on('click', function(e) {
     var $target = $(e.target);

    if($target.hasClass('button-a')) {
        // do something
    } else if($target.hasClass('button-b')) {
        // do another thing
    } else if($target.hasClass('button-c')) {
         // do yet another thing
    }
});
Sushanth --
  • 55,259
  • 9
  • 66
  • 105
  • 2
    This is probably not more efficient than just using multiple delegated event handlers and letting jQuery handle the routing at a bit lower level. – jfriend00 Jun 04 '14 at 23:46
  • @jfriend00: At least a little bit, because jQuery does always evaluate all three conditions - it doesn't know to use `else`. However, the original code seems cleaner to me than doing event delegation manually (and is definitely less error-prone). – Bergi Jun 05 '14 at 02:37
  • this is not using event delegation, it only works if target element has both a button and container class – Aurovrata Sep 09 '20 at 11:47
0

Once you are inside the delegation callback function you can play with the property type to detect what kind of event was triggered then you can watch the id or the className to detect the id or the class from the element. Also remember that you can add more than one class or id to the selector that will be receiving the events and also is possible to add one ore more events. I'm understanding that your container is the most upper element in the DOM tree that will be receiving the events. You can copy&paste the code below in the console from firebug or chrome web inspector. Then click on the top nav from this web page. You will see what happen if not is that you already know it! Also note if you click in the gaps (margin-right:7px space) from each li element you'll trigger the class container (.nav) from all those buttons (Questions | Tags ... | Unanswered).

   $('.container').on('focusout click', ".nav" , function (e) {
    //attached to prevent the stackoverflow itself events attached to this elements
    e.preventDefault();
    e.stopPropagation();
    var className = e.target.className;
    var id = e.target.id;
    if ( e.type === 'click'){
        if ( id === 'nav-questions') {
            // do something
            console.log('clicked: from ' + id + '\n' );
        }
        if ( className=== 'nav mainnavs'){
            // do something
            console.log('clicked: from ' + className + '\n');
        }
        else {
            var selector = id || className;
            console.log('clicked: from ' + selector + '\n');
        }
    }
    if ( e.type === 'focusout'){
        console.log('focusout from ' + id);
    }
});
mario ruiz
  • 880
  • 1
  • 11
  • 28