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


This blog is moved to junaidqadir.com

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(
        $('</pre>
<ul>
	<li><a href="#page' + pageNum + '">' +
	'Page ' + pageNum +
	'<button class="close" title="Remove this page" type="button">×</button>' +
	'</a></li>
</ul>
<pre>

'));

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

    $('#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.

Advertisements

jQuery – Prevent Multiple AJAX Requests


Many times we do not want to take any other requests of the same type while one is still in progress.
A normal post request looks something like:

function doSignup(){
    $.post('http://my-awsomesite/ajax.php',  $('#signupForm').serialize(),
    function(resp){
        if(resp.status == 'OK'){
            alert("Success message");
        }else{
            alert("duh! Signup failed");
        }
    }, 'JSON');
}

Suppose, if we call the function using a link,

<a href="javascript:doSignup()">Signup</a>

Someone does repeated clicks and an enormous amount of requests will be off their way to choke the server to death!
So, to process one request at a time, we’ll modify the above function to something like this:

/**
 *Let's define a variable that acts similar to the 'On Air' light. When
 *its active (true in this case), we will just return from the doSignup function
 * silently or inform the user via a jquery-ui dialog or something like that.
 */
var isProcessing = false;

function doSignup(){
    if(isProcessing){
        /*
         *This won't go past this condition while
         *isProcessing is true.
         *You could even display a message.
         **/
        return;
    }

    /**
     *set isProcessing to true right before the $.post (or anyother method
     *of the sort like $.ajax, $.get) is called
     */
    isProcessing = true;
    $.post('http://awsomesite/ajax.php',  $('#signupForm').serialize(),
        function(resp){
            isProcessing = false;
            if(resp.status == 'OK'){
                alert("Success message");
            }else{
                alert("duh! Signup failed");

            }
        }, 'JSON');
}

The code is pretty straight-forward, you define a variable that is visible to your function.
Then inside your function you write a conditional statement to check whether the variable is true, initially it is false.
If it’s false then the code continues and just before the AJAX action (get, post, etc) is performed, you’ll change the variable to true. And as soon as the AJAX action completes its trip to the server, you turn that variable to false again.
While the AJAX action is processing if the user tries to click the signup link, either you prompt him/her to wait or simply ignore his actions.

As I mentioned earlier of repeated user clicks, another concern arises, we have to tackle after how much delay a request should go in order to prevent unnecessary requests to the server. I’ll try to cover that in a future post.

Thanks for reading, have a great weekend.