javascriptjqueryjquery-uijquery-eventsjquery-ui-tabs

Why parents tabsshow-event triggered by childtab?


I have a tab (called firsttab) with in his content another tab (called childtab). We bind the tabshow-event to the firsttab.

If we click to one of the tabs in "firsttab" all work fine (Tab 1 - Tab 5). If we click to one of the "childtab" tabs (Tab 1.1 - Tab 1.3) the tabshow-event who are bind to the "firsttab" is triggerd.

Testcase: http://jsfiddle.net/bM8Wh/

HTML:

<div id="firsttab">
    <ul>
        <li><a href="#firsttab_1">Tab 1</a></li>
        <li><a href="#firsttab_2">Tab 2</a></li>
        <li><a href="#firsttab_3">Tab 3</a></li>
        <li><a href="#firsttab_4">Tab 4</a></li>
        <li><a href="#firsttab_5">Tab 5</a></li>
    </ul>
    
    <div id="firsttab_1">
        <div id="childtab">
            <ul>
                <li><a href="#childtab_1">Tab 1.1</a></li>
                <li><a href="#childtab_2">Tab 1.2</a></li>
                <li><a href="#childtab_3">Tab 1.3</a></li>
            </ul>
            
            <div id="childtab_1">Tab 1.1</div>            
            <div id="childtab_2">Tab 1.2</div>
            <div id="childtab_3">Tab 1.3</div>
        </div>
    </div>
    <div id="firsttab_2">Tab 2</div>
    <div id="firsttab_3">Tab 3</div>
    <div id="firsttab_4">Tab 4</div>
    <div id="firsttab_5">Tab 5</div>
</div>

JavaScript:

$("#firsttab, #childtab").tabs();
$("#firsttab").bind('tabsshow', function(event, ui) { funcX(ui.index); });
  
function funcX(idx){
    alert('triggerd - index: ' + idx);
}

I don't understand why the tabsshow-event is triggered by the childtab because I bind this event to the firsttab.

The answer of my jQuery-ticked was:

"Events bubble; check the target."

but I don't understand what it means.

I handle the problem by change my tabsshow-event-handler to:

$("#tabs").bind('tabsshow',
  function(event, ui) {
    if ((/#(.*?)$/im).exec(ui.tab.hash)[1] == this.id)
      funcX(ui.index);
  });

but I will understand where are the problem.


Solution

  • By default, event's bubble, meaning that an event in a child element goes up to all parent elements unless you stop it. So for example a click anywhere on the page is a click event on that element, it's parent, and so on up until document. This behavior also happens with any custom jQuery events like tabsshow, but if you don't want it you can stop the event from bubbling using event.stopPropagation(), like this:

    $("#childtab").bind('tabsshow', function(event, ui) { 
      event.stopPropagation(); 
    });
    

    This stops the event from firing on #firsttab because it just doesn't bubble up there anymore. You can try your sample with this fix here.