JayKandari
JayKandari

Reputation: 1248

Override a delegated event handler for a specific element only in jQuery

Consider the following code:

<div id="main">
  <ul>
     <li>
       <span>Normal text</span>
    </li>
    <li>
       <span class="special">Special text</span>
    </li>
  </ul>
</div>

And following JS for above HTML.

(function($) {
  console.clear();
  console.log('hello');

  // (1) main click handler. 
  $(document).on('click', 'span', function(e) {
    console.log('Span :' + e.target.textContent)
  })

  // (2) unbind all the clickhandler on span.
  $(document).off('click', 'span');

  // (3) Override just the .special span click handler.
  $(document).on('click', 'span.special', function(e) {
    e.stopPropagation();
    console.log('Special Item: ' + e.target.textContent)
  })

})(jQuery);

Here, the objective is to not run the main click handler (1) on span.special click.

If I do (2). which removes all the attached handlers. I want to preserve the main click handler(1) for other spans.

How can I explicitly override the delegated click handler for an individual item?

Thanks in advance.

https://codepen.io/JayKandari/pen/oNjmzBm?editors=1011

Update: If the code in (1) main click handler is coming from another library and cannot be changed directly. How is this possible in this case?

Upvotes: 0

Views: 256

Answers (1)

Kalimah
Kalimah

Reputation: 11437

You can specify different handlers for span without .special and spans with it.

To override existing handler you can do so by extracting the handler that was already assigned then turn off handlers for all spans. Then assign to each type separately.

Using .off("click", "span.special") because .off() only works with the exact same selector that .on() used.

See this example:

(function($) {
  console.clear();
  console.log('hello');

  $(document).on('click', 'span', function(e) {
    console.log('Span :' + e.target.textContent, e.target);
  });

  // Get all events attached to document to extract handler
  let events = $._data(document, 'events');
  let handler;
  jQuery.each(events['click'], function(type, data) {
    // Check selector to extract handler
    if (data.selector == "span")
      handler = data.handler;
  });

  // unbind all the clickhandler on span.
  $(document).off('click', 'span');

  // Attach to all spans except special
  $(document).on('click', 'span:not(.special)', handler);

  // attach only to special
  $(document).on('click', 'span.special', function(e) {
    e.stopPropagation();
    console.log('Special Item: ' + e.target.textContent)
  })

})(jQuery);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="main">
  <ul>
    <li>
      <span>Normal text</span>
    </li>
    <li>
      <span class="special">Special text</span>
    </li>
  </ul>
</div>

Upvotes: 1

Related Questions