Dynamically Add, Remove and Re-number Tabs in Twitter Bootstrap

NEWS: Bootstrap 3 is out! Currently a RC1

Earlier today, I was working on a web app with Twitter Bootstrap and I was required to have tabs which the user can add or remove. Unfortunately Bootstrap doesn’t give you the close button on a tab out-of-the-box. So I quickly went to the Bootstrap’s Issues page on GitHub where I stumbled upon the very problem I was facing.

A guy, one of the maintainers of the project was of the opinion:

I don’t think we’ll be adding this as native functionality, but feel free to file an issue later if you wish to add whatever solution you come up with to the wiki for forks/extensions/etc.

I was like wow! Now, everyone was proposing their way of doing it. So, I came up with my solution thanks to this guy who proposed this solution. He just gave an heads-up and that was all I needed, then I sat and wrote the three features I needed i.e. Add, Remove and renumber the tabs (if in case one is removed from the middle. and yeah, the first tab cannot be removed).
The Code

The following code assumes Bootstrap and jQuery scripts and style are loaded accordingly and the code is called on

 $(doument).ready()

and

var pageNum = 1;

is defined in the global scope (I know I know :)).

/**
 * Add a Tab
 */
$('#btnAddPage').click(function () {
    pageNum++;
    $('#pageTab').append($('<ul><li><a href="#page' + pageNum + '">' +
            'Page ' + pageNum +
            '<button class="close" title="Remove this page" type="button">×</button>' +
            '</a></li>< /ul>'));

    $('#pageTabContent').append(
            $('<div class="tab-pane" id="page' + pageNum +
                    '">Content page' + pageNum + '</div>'));

    $('#page' + pageNum).tab('show');
});

/**
 * Remove a Tab
 */
$('#pageTab').on('click', ' li a .close', function () {
    var tabId = $(this).parents('li').children('a').attr('href');
    $(this).parents('li').remove('li');
    $(tabId).remove();
    reNumberPages();
    $('#pageTab a:first').tab('show');
});

/**
 * Click Tab to show its contents
 */
$("#pageTab").on("click", "a", function (e) {
    e.preventDefault();
    $(this).tab('show');
});

/**
 * Reset numbering on tab buttons
 */
function reNumberPages() {
    pageNum = 1;
    var tabCount = $('#pageTab > li').length;
    $('#pageTab > li').each(function () {
        var pageId = $(this).children('a').attr('href');
        if (pageId == "#page1") {
            return true;
        }
        pageNum++;
        $(this).children('a').html('Page ' + pageNum +
                '<button class="close" title="Remove this page" type="button">×</button>');
    });
}

The Demo

Check out the demo here.

Please like and share the post if you enjoyed it and if it helped you.

Author: JQ

JQ is a Full-Stack developer with 10+ years of programming experience. He is a fan of Linux and the many distros made around the kernel. He enjoys music while coding and his favourite genres range from classical Balochi Zahirok to Metal Rock.

  • This is great except for a couple of things:
    1. If you add 2 tabs so you have tabs 1, 2, and 3. Then remove tab 2, then add another tab, the content ids will get duplicated (you will have 2 contents with the id of page3.

    2. I would put this in a namespace so you don’t have to use globals (pageNum)
    (function( MyPageTabs, $, undefined ) {
    MyPageTabs.init = function()
    {
    // do your initialization here (bind events etc)
    };

    var pageNum = 1;

    function addTab()
    {
    // …
    }

    function removeTab()
    {
    // …
    }

    function renumberTabs()
    {
    // ….
    }
    }(window.MyPageTabs = window.MyPageTabs || {}, jQuery));

    // On Document Load Ready
    $(function() {
    MyPageTabs.init();
    });

    3. I would also add the elements using jQuery rather than strings:
    var newRemoveIcon = $(‘).addClass(‘close’)…;
    var newTabLink = $(‘‘).attr(‘href’, ‘…’)…append(newRemoveIcon);
    var newTab = $(‘).append(newTabLink);