1

I have some links on my site for which I am trying to trigger a click event handler. In HTML, the content where the links occur is like so:

<div class = "panel-container messages">
  <div class="ld-course-navigation">
    <ul class="ld-table-list notificationsList">
         <li class="notification-item">
             <a href="somelink?read=id" class="grid gs8 gsx"> 
               <div class="fa Webinar site-icon grid--cell"></div>
               <div class="item-content grid--cell fl1">
                   <div class="item-header">            
                      <span class="item-type ">Webinar</span>
                      <span class="item-creation">
                         <span title="title" class="relativetime">3 hours ago</span> 
                      </span> 
                  </div>        
                  <div class="item-location">A live webinar has started</div>       
               </div>
            </a>
         </li>
     </ul>
  </div>
</div>

The code I was using was

$(".notification-item a").click(function (e) {
    e.preventDefault();
    console.log('clicked notification');
    // do some stuff, first seeing if the url has the read url param
});

I really just need to run this handler when the url clicked is one containing the url param read but wasn't sure how to do that so just decided to tend to that checking inside the handler.

With above, I noticed the handler was not triggering. Then I noticed that in one of my site's plugins (it is a Wordpress site), there was this click function:

$('body').on('click', '.ld-course-navigation a', function(e) {
    if ($(window).width() < 900) {
        e.preventDefault();
        console.log('clicked link on narrow screen to ' + $(this).attr('href'));
        closeFocusSidebar();
        window.location.href = $(this).attr('href');
    }
});

where .ld-course-navigation a of course is also selecting the links of the sort I show above, and the console output showed it was being called.

So I got to thinking this must be some sort of case where only one of these click functions is being allowed to run.

Now I read this question and I understand that multiple click functions should indeed be able to run, but only one will run if you are using inline onclick.

As far as I can tell, my implementation does not amount to inline usage (or does it?), so not sure how to ensure that my click handler works.

What can I try next? Ideally it would amount to not touching the plugin's JavaScript and just editing my own.

halfer
  • 19,824
  • 17
  • 99
  • 186
Brian
  • 561
  • 5
  • 16

1 Answers1

1

multiple click functions should indeed be able to run, but only one will run if you are using inline onclick

No, that's not quite what the linked answer says. It says that if you use an inline onclick, something like:

<a onclick="runSomeJavascriptFunction();">Click me</a>

then you can only have that one click handler on an element. Inline like that is considered bad practice, and you're not doing it anyway, so that isn't relevant here.

You can have many click handlers on an element, and unless explicitly stopped, they'll all run fine, even "bubbling" up to parent elements.

So, why isn't yours working? Well, the WP plugin code is using delegation (see Direct and delegated event handlers) by passing a selector context:

$('body').on('click', '.ld-course-navigation a', function(e) {

This is typically done when the target elements are injected into the page after page load. My guess is this is a clue to the problem.

The selector you use for this handler:

$(".notification-item a").click(function (e) {

will only work for any <a> links inside a .notification-item that exist when the page is first loaded. If some AJAX or some user interaction later on adds some more links or elements that would ordinarily match that selector, that selector won't catch them, because jQuery does not know about them.

If you know that is going to happen, you can target a parent element that does exist on page load, and then filter to only match the child elements you want. The WP plugin code for eg targets the body, which obviously exists on page load. So every click on the page, anywhere, will be handled - but they are filtered with the extra selector context: .ld-course-navigation a. Only things tht match that filter are actually handled. That filtering happens "live", at the time the click happens, so if some new elements have been added, this will find and handle them!

Since the WP plugin code uses that format, my guess is there are elements being injected after page load. And that's why your handler isn't working - it won't match the new elements. Try updating it to attach to the body, but filtered on your targets:

$("body").on('click', '.notification-item a', function (e) {

Here's another question with lots of info about this.

Don't Panic
  • 13,965
  • 5
  • 32
  • 51
  • Very interesting! Thanks for enlightening me - indeed on page load I have `
      ` and in my javascript I use Pusher channels as well as ajax call to a notifications database to receive notifications that I place in the DOM. So now I guess I have some work to do! thanks again
      – Brian Oct 27 '21 at 09:57
    • OK, sounds like that is the issue then. Instead of attaching to `body`, you could use your `.notificationsList`, since it also exists at page load. That way the handler will process only clicks that are relevant. `$(".notificationsList").on('click', '.notification-item a', function (e) { ...` – Don't Panic Oct 27 '21 at 10:19
    • Hi, I have it working with `$("body").on('click', '.notification-item a', function (e) {` as you suggested – Brian Oct 31 '21 at 10:44