Hugo Tunius
Hugo Tunius

Reputation: 2879

jQuery .on delegation, only direct children in selector

I am trying to use .on to bind an event only to direct children of an element.

The dom looks like this:

table > tbody > tr+ > td > table > tbody > tr+

So far I have tried:

None of these works as expected and using table.on("dbclick", "tr", listenerFunction) collides with the nested table causing double triggers and the likes because both tables have this listener.

Any ideas most appreciated.

<table>
  <tbody>
   <tr><!--Selectable row, adds the row after with sub table --></tr>
    <tr>
      <td>
        <table>
          <tbody>
            <tr></tr>
          </tbody>
        </table>
      </td>
    </tr>
  </tbody>
</table>

Upvotes: 4

Views: 2095

Answers (5)

closure
closure

Reputation: 7452

My suggestion would be to either add an id or class to the child table. This would ensure that it doesn't conflict with any other element on the page or any modification that happens in future. Suppose you add a class nested-table to child table. The code will look like this:

$('table.nested-table tr').dblclick(listenerFunc)

As you have indicated that you reference to table, this should work:

table.on('dblclick', 'tr', listenerFunc)

Upvotes: 2

Hugo Tunius
Hugo Tunius

Reputation: 2879

It turns out that this is in part me forgetting to prevent event bubbling and in part a bug/missing feature in jquery 1.7.

The same code in two jsfiddles

In jQuery 1.7.2 passing ">tr" as the selector to .on does not work, I do not know if this is a bug or something that's just not implement in 1.7.2 however the .on method was added in 1.7.

The following code reproduces the error. I've tested this on Chrome running on Mountain Lion and Chrome running on window 7

HMTL:

<table id="outer">
    <tbody>
        <tr id="outer-row">
            <td>Hello</td>
            <td>World</td>
        </tr>
        <tr id="outer-row-1">
            <td>
                <table id="inner">
                    <tbody>
                        <tr id="inner-row">
                            <td>nested
                            </td>
                         </tr>
                    </tbody>
                </table>
            </td>
        </tr>
    </tbody>
</table>

JS:

$(function() {
    var handle = function(e) {
        console.dir(this.id);
    };


    $("#outer").children("tbody").on("dblclick", ">tr", handle);
    $("#inner").children("tbody").on("dblclick", ">tr", handle);
});

Upvotes: 0

Arun P Johny
Arun P Johny

Reputation: 388316

Try

var table = $('#tbl')
table.on("click", "> tbody > tr", listenerFunction);

function listenerFunction(e){
    if(!$(this).children().filter($(e.target).closest('td')).length){
        return;
    }
    console.log('direc tr')
}

Demo: Fiddle

Upvotes: 0

Fr&#233;d&#233;ric Hamidi
Fr&#233;d&#233;ric Hamidi

Reputation: 262919

If your first <table> is not nested itself, you can provide a selector that only matches <tr> elements that are not descendants of other <tr> elements:

table.on("dbclick", "tr:not(tr tr)", listenerFunction);

Upvotes: 0

Rory McCrossan
Rory McCrossan

Reputation: 337560

In your listener function use event.stopPropagation to stop the event bubbling back up to a parent tr.

function listenerFunc(e) {
    e.stopPropagation();

    // Do your thing...
}

Upvotes: 6

Related Questions