Search code examples
javascripthtmljquery-tabs

Javascript tab navigation issue


I was wondering if anybody could help me with a fix for an error in the following script.

Everything works fine until I add a second line with the same links, then the behavior is not as expected.

This is a simple script to hide and show tabs.

At some point, when clicking on both top and bottom row of links, 2 tabs are displayed at the same time.

There's a live example on: http://jsfiddle.net/8cwqH/1/

<ul class="tabs">
<li><a href="#tab1">Tab1</a></li>
<li><a href="#tab2">Tab2</a></li>
<li><a href="#tab3">Tab3</a></li>
</ul>

<div id="tab1">
 tab1<br />tab1<br />
 tab1<br />tab1<br />
</div>

<div id="tab2">
 tab2<br />tab2<br />
 tab2<br />tab2<br />
</div>

<div id="tab3">
 tab3<br />tab3<br />
 tab3<br />tab3<br />
</div>

<br />

<div class="othertabs">
 <a href="#tab1">Tab1</a>
 <a href="#tab2">Tab2</a>
 <a href="#tab3">Tab3</a>
</div>

<a href="#tab2">tab 2 link</a>

This is the script:

// Wait until the DOM has loaded before querying the document
$(document).ready(function(){
    $('ul.tabs, div.othertabs').each(function(){
        // For each set of tabs, we want to keep track of
        // which tab is active and it's associated content
        var $active, $content, $links = $(this).find('a');

        // If the location.hash matches one of the links, use that as the active tab.
        // If no match is found, use the first link as the initial active tab.
        $active = $($links.filter('[href="'+location.hash+'"]')[0] || $links[0]);
        $active.addClass('active');
        $content = $($active.attr('href'));

        // Hide the remaining content
        $links.not($active).each(function () {
            $($(this).attr('href')).hide();
        });

        // Bind the click event handler
        $(this).on('click', 'a', function(e){
            // Make the old tab inactive.
            $active.removeClass('active');
            $content.hide();

            // Update the variables with the new link and content
            $active = $(this);
            $content = $($(this).attr('href'));

            // Make the tab active.
            $active.addClass('active');
            $content.fadeIn();

            // Prevent the anchor's default click action
            e.preventDefault();
        });
    });
});

Solution

  • You're redeclaring the $active and $content variables in each iteration of the loop. This means that clicking Tab3 in one set of tabs, then Tab2 in the other will cause both tabs to appear at the same time.

    You need to refactor your code to move those two variable outside of the loop, and will probably want to set the active variable to a string (e.g. #tab1) so that it doesn't matter which tab set you click on (at the moment, your $active variable points to a specific tab in one of the tab sets).

    Here is a working example with the modifications I've mentioned; http://jsfiddle.net/8cwqH/2/