Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does e.currentTarget change with jQuery's event delegation?

http://jsbin.com/xaguxuhiwu/1/edit?html,js,console,output

  <div id="container">
    <button id="foo">Foo button</button>
    <button id="bar">Bar button</button>
  </div>

$('#container').on('click', function(e) {
  var targetId = e.target.getAttribute('id');
  // Manually do event delegation
  if (targetId === 'foo') {
    var currentId = e.currentTarget.getAttribute('id');
    console.log('without delegation, currentTarget is: ' + currentId);
  }
});

$('#container').on('click', '#foo', function(e) {
    var currentId = e.currentTarget.getAttribute('id');
    console.log('with delegation, currentTarget is: ' + currentId);
});

Basically, my understanding of e.currentTarget for an event is that it reflects the point to which the event has bubbled to. Since I have an event listener on the #container element, I would expect the currentTarget to be container in both scenarios.

This is true for the standard on handler, as shown by the first example. However, when using event delegation (the #foo argument on the second click), currentTarget changes to be the inner button.

Why does the e.currentTarget change between the two scenarios? Specifically, in the latter case, does this mean that jQuery is not putting the event listener on the parent (#container) element?

like image 225
AnilRedshift Avatar asked Sep 03 '25 05:09

AnilRedshift


1 Answers

Basically it's because of jQuery magic behind the scenes. The jQuery event object that wraps the native event is changing the currentTarget, to be what might be more-convenient.

To access the value normally pointed to by currentTarget, jQuery events have delegateTarget.

This property is most often useful in delegated events attached by .delegate() or .on(), where the event handler is attached at an ancestor of the element being processed. It can be used, for example, to identify and remove event handlers at the delegation point.

For non-delegated event handlers attached directly to an element, event.delegateTarget will always be equal to event.currentTarget.

You can see that in the originalEvent, currentTarget has the value you would expect.

$('#container').on('click', function(e) {
    console.log('without delegation:');
    console.log('target: ' + e.target.getAttribute('id'));
    console.log('currentTarget: ' + e.currentTarget.getAttribute('id'));
    console.log('originalEvent.currentTarget: ' + e.originalEvent.currentTarget.getAttribute('id'));
    console.log('delegateTarget: ' + e.delegateTarget.getAttribute('id'));
    console.log('--');
});
$('#container').on('click', '#foo', function(e) {
    console.log('with delegation:');
    console.log('target: ' + e.target.getAttribute('id'));
    console.log('currentTarget: ' + e.currentTarget.getAttribute('id'));
    console.log('originalEvent.currentTarget: ' + e.originalEvent.currentTarget.getAttribute('id'));
    console.log('delegateTarget: ' + e.delegateTarget.getAttribute('id'));
    console.log('--');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="container">
    <button id="foo">Foo button</button>
    <button id="bar">Bar button</button>
</div>
like image 149
Alexander O'Mara Avatar answered Sep 04 '25 20:09

Alexander O'Mara