Sidney Sousa
Sidney Sousa

Reputation: 3614

How to make dynamic tabs using jquery

I have this code for now aiming to create tabs:

    <ul class="nav nav-tabs">
        <li class="active">
            <a href="#custom-tab-0-8cf04a9734132302f96da8e113e80ce5" data-toggle="tab">Home</a>
        </li>
        <li>
            <a href="#custom-tab-0-cce99c598cfdb9773ab041d54c3d973a" data-toggle="tab">Profile</a>
        </li>
    </ul>
    <div class="tab-content">
        <div id="custom-tab-0-8cf04a9734132302f96da8e113e80ce5" class="tab-pane active" tabindex="-1">
            Content goes here<br>
        </div>
        <div id="custom-tab-0-cce99c598cfdb9773ab041d54c3d973a" class="tab-pane" tabindex="-1">
            Nothing comes here<br>
        </div>
    </div>

CSS:

ul.nav.nav-tabs {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
    margin-top: 2%;
}

ul.nav.nav-tabs li {
    float: left;
}
ul.nav.nav-tabs a {
    display: inline-block;
    color: black;
    text-align: center;
    padding: 14px 16px;
    text-decoration: none;
    transition: 0.3s;
    font-size: 17px;
}
li.active {
    background-color: #ccc;
}

How can I create multiple tabs with jQuery, display the content of the the TAB that I click only and add a class active to it?

Note: I cannot change much on the html structure because it is a WordPress site and I used short-code to generate the tabs. I simply styled and tried the jQuery.

For now I can see all the content of all tabs at once.But what I want is only one tab active and the others closed. When I click on a next tab,it should display the content of that tab online,have the class active and deactivate the class active that the previous active tab had.

I started using this code just to test functionality when I click on each TAB but I don't think it is a good practice to use child selectors cause I might have more than 2 tabs:

$(document).ready(function()  {
    $("ul.nav.nav-tabs li:first-child a").click(function(){
        alert("You clicked on the first-child");
    });
    $("ul.nav.nav-tabs li:nth-child(2) a").click(function(){
        alert("You clicked on the second child");
    });            
});

Thanks in advance.

Upvotes: 0

Views: 2441

Answers (2)

Satpal
Satpal

Reputation: 133453

You can use index(element) method to get the index of element which is clicked in collection on matched elements. Note it return zero based position.

Search for a given element from among the matched elements.

//Hide inactive tab content
$('.tab-content :not(.active)').hide();

//Cache elements 
var navigationAnchorElements = $("ul.nav.nav-tabs li a");

//bind click handler
navigationAnchorElements.click(function(e) {
    e.preventDefault();

    //remove active class and hide content pane
    $('.tab-content .active').removeClass('active').hide();

    //Show current active content pane and add Class
    $(this.getAttribute("href")).addClass('active').show();

    //remove active class from parent elemets
    $("ul.nav.nav-tabs li.active").removeClass('active');

    //add active class to current element
    $(this).parent().addClass('active');

    var index = navigationAnchorElements.index(this) + 1;
    alert("You clicked on the " + index + " child" );
});

$(document).ready(function() {
  var navigationAnchorElements = $("ul.nav.nav-tabs li a");
  $('.tab-content :not(.active)').hide();
  navigationAnchorElements.click(function(e) {
    e.preventDefault();
    $('.tab-content .active').removeClass('active').hide();
    $(this.getAttribute("href")).addClass('active').show();

    $("ul.nav.nav-tabs li.active").removeClass('active');
    $(this).parent().addClass('active');

    var index = navigationAnchorElements.index(this) + 1;
    //  alert("You clicked on the " + index + " child" + this.dataset.id);
  });
});
ul.nav.nav-tabs {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid #ccc;
  background-color: #f1f1f1;
  margin-top: 2%;
}
ul.nav.nav-tabs li {
  float: left;
}
ul.nav.nav-tabs a {
  display: inline-block;
  color: black;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
  transition: 0.3s;
  font-size: 17px;
}
li.active {
  background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav nav-tabs">
  <li class="active">
    <a href="#custom-tab-0-8cf04a9734132302f96da8e113e80ce5" data-toggle="tab">Home</a>
  </li>
  <li>
    <a href="#custom-tab-0-cce99c598cfdb9773ab041d54c3d973a" data-toggle="tab">Profile</a>
  </li>
</ul>
<div class="tab-content">
  <div id="custom-tab-0-8cf04a9734132302f96da8e113e80ce5" class="tab-pane active" tabindex="-1">
    Content goes here
    <br>
  </div>
  <div id="custom-tab-0-cce99c598cfdb9773ab041d54c3d973a" class="tab-pane" tabindex="-1">
    Nothing comes here
    <br>
  </div>
</div>

Upvotes: 0

Lajos Arpad
Lajos Arpad

Reputation: 77030

Check out Visiblary:

/*
 * params:
 *     - selector: jQuery selector
 *     - init: function which gets the Visiblary object to initialize it
 *     - events: object/array
 *         - root: a selector which contain all the affected tags, default is "body"
 *         - types: array, which contains the string representation of the events
 *         - selector: inner selector to identify the target set
 *         - handler: handler function
 */
function Visiblary(params) {
    var instance = this;
    if (!params.toggleClass) {
        params.toggleClass = "invisible";
    }
    this.hideAll = function() {
        $(params.selector).addClass(params.toggleClass);
        return instance;
    };
    this.hideSubset = function(subsetSelector) {
        $(params.selector).filter(subsetSelector).addClass(params.toggleClass);
        return instance;
    };
    this.hideOnly = function(subsetSelector) {
        $(params.selector).not(subsetSelector).removeClass(params.toggleClass);
        $(params.selector).filter(subsetSelector).addClass(params.toggleClass);
        return instance;
    };
    this.showAll = function() {
        $(params.selector).removeClass(params.toggleClass);
        return instance;
    };
    this.showSubset = function(subsetSelector) {
        $(params.selector).filter(subsetSelector).removeClass(params.toggleClass);
        return instance;
    };
    this.showOnly = function(subsetSelector) {
        $(params.selector).not(subsetSelector).addClass(params.toggleClass);
        $(params.selector).filter(subsetSelector).removeClass(params.toggleClass);
        return instance;
    };
    this.invert = function() {
        $(params.selector).each(function() {
            $(this).hasClass(params.toggleClass) ? $(this).removeClass(params.toggleClass) : $(this).addClass(params.toggleClass);
        });
        return instance;
    };
    if (!!params.init) {
        params.init(this);
    }
    if (!!params.events) {
        for (var event in params.events) {
            $(!!params.events[event].root ? params.events[event].root : "body").on(params.events[event].types.join(" "), params.events[event].selector, params.events[event].handler);
        }
    }
    return instance;
}

With that you can achieve what you want and more. invisible is a CSS class:

.invisible {
    display: none;
}

EDIT:

This file should be a separate .js file inside a script tag positioned below the script which loads jQuery. It is recommended to initialize your Visiblary objects inside the load event of $(function() {}). Example:

$(function() {
    //New visiblary object, things will be callable using visiblary.
    var visiblary = Visiblary({
        //Elements corresponding to selector
        selector: "#chat-window > .chat-content",
        //In this example we have a single event, which is clicking on
        //a .chat-tab-set child of #chat-window. This will trigger showOnly
        //with the index corresponding data-index
        events: [
            {
                root: "#chat-window > .chat-tab-set",
                types: ["click"],
                selector: ".chat-tab",
                handler: function() {
                    visiblary.showOnly(":eq(" + $(this).data("index") + ")");
                }
            }
        ]
    });
});

Upvotes: 1

Related Questions