views:

68

answers:

3

Hi,

I'm trying to have different delegate click handlers for different elements within "li" elements in a list. Example:

<ul id='myList'>
  <li>
    <p>First item.</p>
    <button>button1</button>
    <button>button2</button>
  </li>
  <li>
    <p>Second item.</p>
    <button>button1</button>
    <button>button2</button>
  </li>
</ul>

when the user clicks button1 (of any item) I want to grab that event, and stop propagation (same for button2 instances). The user clicking the parent li element would be a different handler:

$('#myList').delegate('li', 'click', function() {
    alert("You clicked a parent <li> item!");
});

$('#myList').delegate('button', 'click', function(event) {
    event.stopPropagation();
    event.stopImmediatePropagation();
    alert("You clicked a button (but which one?)!");
});

So one issue is, how do I have a delegate for button1 instances, and another for button2 instances? The second delegate in the example above does fire when a button is clicked, but event.stopPropagation() doesn't seem to work as the handler for the parent li item still gets called,

------ Update --------------

Also trying to call event.stopImmediatePropagation(), no effect though, parent handler still being called too.

Thank you

A: 

You can try event.stopImmediatePropagation(). Theoretically, what you have should work, so expanding it might help.

Aaron Harun
Yeah no luck, tried adding it but parent handler still gets called.
A: 

Indeed, it should work, and I tried to step through the jQuery code, but to no avail. Instead, I made this:

(function(){
  var el = document.getElementsByTagName("li");
  var i = el.length;

  while (i--)
    el[i].onclick = function () {
      alert("You clicked a parent <li> item!");
    };

  el = document.getElementsByTagName("button");
  i = el.length;

  while (i--)
    el[i].onclick = function (event) {
      var e = event || window.event;

      e.stopPropagation();
      e.cancelBubble = true;
      alert("You clicked a button (but which one?)!");
    };

})();

which works the way you want it to work (not tested in IE, though). I'm to tired to look into this further, now, perhaps tomorrow.

To answer your other question: I think you should really add ids or classes to your <button>s, so you can easily test which button got called.

Marcel Korpel
+1  A: 

Maybe in the parent:

$('#myList').delegate('li', 'click', function(event) {
    if (!$(event.target).is('button')) {
        alert("You clicked a parent <li> item!");
    }
});
Mark
Ok using this as the model works, I set a different class for each button type, then in this one parent handler I check the target type/class, thanks.
Seems like a bug in jQuery to me, as that's what delegate should be doing - matching the event target against the selector. Does look that way - http://jsfiddle.net/SxsbK/
Anurag