Search code examples
javascriptjqueryevent-handlingjquery-1.7jquery-on

jQuery .on() not firing event handler


Scenario

I have a list of users, within each list item is a <header> and a <div> wrapper - they are siblings:

<li class="user">
    <header>
        // ...
    </header>
    <div class="user-wrapper">
        // ...
    </div>
</li>

I am toggling the div wrapper when the user header is clicked.

What currently works:

// the handler is called
$('li.user > header').live('click', function () {
    $(this).next('.user-wrapper').toggle();
});

As live() has been deprecated and I am using jQuery 1.7.2, I want to use on().

What does not work:

// Direct style
$('li.user > header').on('click', function () {
    $(this).next('.user-wrapper').toggle();
});

// Delegated style
$('li.user').on('click', 'header', function () {
    $(this).next('.user-wrapper').toggle();
});

In either on() scenario, the anonymous handler function is not being called.

Question

First... why is on() choking?

Second... if/when it works, using the delegate style, can i still reference the header's sibling div in the same manner as above?


Solution

  • [EDITED]

    For delegate event handling the syntax of .on() is:

    // 'element' must be static and an ancestor to 'target'.
    $(element).on(eventName, target, handlerFunction);
    

    Your delegate scenario above should work, assuming your li.user tags are static at the time of binding.

    $('li.user').on('click', 'header', function () {
        $(this).next('.user-wrapper').toggle();
    });
    

    If you test this in jsFiddle, it works as is. It seems like your li.user elements are being created dynamically.

    If li.user is dynamically created then use a different (static) parent selector. If your list ul is always present, for example:

    // HTML
    <ul class="user-list">
      <li class="user">
        <header>
            // ...
        </header>
        <div class="user-wrapper">
            // ...
        </div>
      </li>
    </ul>
    
    // JavaScript
    $('ul.user-list').on('click', 'li.user > header', function() {
      $(this).next('.user-wrapper').toggle();
    });