wordSmith
wordSmith

Reputation: 3183

Trigger event on parent originating, bubbling up from child

If I have a <div class="timely"></div> containing a table, in that table is a <th class="prev"><i>previous</i></th>...Chrome dev tools say there is an event listener on the <th>, but Firefox dev tools points out it is not on the <th>, but the parent .timely, which Chrome also points out when viewing what is in the handler for this event.

What I am trying to do is replicate what happens on click, to happen on keyup. It doesn't seem as simple as, in jQuery:

$('.timely th').each(function(){
    $(this).on('keyup', function(){
        $(this).trigger('click');
    });
});

Because the event handler is on the .timely and it is listening from where the event bubbled up from when executing the code.

How can I replicate the click event on keyup of .timely with the context of it bubbling from the <th>?

Upvotes: 2

Views: 304

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074266

First, note there's no reason for your each loop (unless you're doing something else in it you haven't shown). Remember that jQuery is set-based, so $("selector").on(...) sets up the handler on all elements in the set.

Re your question: Accept the event argument and use its target property as the element on which to trigger:

$('.timely th').on('keyup', function(e) {
    $(e.target).trigger('click');
});

Or if you want to handle it up on .timely instead of on the th in .timely, just change the selector and use the delegating form (assuming you only want this for the th elements):

$('.timely').on('keyup', 'th', function(e) {
    $(e.target).trigger('click');
});

It's tricky to get keyup on a th element, of course; the only way immediately coming to mind is to put an input element in the th so the keyup bubbles:

$('.timely th').on('keyup', function(e) {
    console.log("keyup");
    $(e.target).trigger('click');
});
$('.timely th').on('click', function(e) {
    console.log('click');
});
<div class="timely">
  <table>
    <tbody>
      <tr>
        <th>
          <input type="text">
        </th>
      </tr>
    </tbody>
  </table>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


You haven't said why you want to trigger click on keyup, but if it's just to run the click event handler, I don't recommend doing that. Instead, just use the same function for both the keyup and click handler. You can hook multiple events just by space-delimiting them in .on (.on("click keyup", ...)), or use a named function and refer to it where you hook up your click and keyup handlers.


Chrome dev tools say there is an event listener on the <th>, but Firefox dev tools points out it is not on the <th>, but the parent .timely

If you don't want to see handlers attached to ancestors, untick the Ancestors box in the Event Listeners tab:

enter image description here

But note that in your example code, the handler is definitely on the th, not the ancestor .timely element.

Upvotes: 3

qiAlex
qiAlex

Reputation: 4346

this jquery magic may not will work fast

$('.timely th').each(function(){
    $(this).on('keyup', function(){
        $(this).trigger('click');
    });
});   

you can abstract function that you want use on click and on keyup

function clickKeyupHandler (e) {
  // ...
}

// somewhere when you use it use same functions to handle click and keyup
// $('.timely').on('click', clickKeyupHandler);

$('.timely').on('keyup', 'th', clickKeyupHandler);

Upvotes: 0

Related Questions