Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap, nav-tabs, dropdown menus; how to set active tab based on URI

I'm using Bootstrap nav-tabs/dropdown menus component as my primary navigation bar but I cant figure out how to set the active menu based on an incoming URI.

There are a lot of different examples/posts on the net that use nav-tabs for hiding and displaying specific div content or working with the # symbol but I just want to read the incoming URI using PHP, the _SERVER["REQUEST_URI"] variable and set a tab active. Be it a nested location in the navigation or not is also a problem.

Here what I've been trying:

<ul class="nav nav-tabs" id="supernav">
    <li class="active"><a href="/page1.html" data-toggle="tab"><i class="icon-home" style="margin-top:4px;"></i> Page 1</a></li>
    <li class="dropdown">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Page 2 <b class="caret"></b></a>
        <ul class="dropdown-menu">
            <li><a href="/page2.html" data-toggle="tab">Home</a></li>
            <li class="divider"></li>
            <li><a href="/page2.2.html" data-toggle="tab">Page 2.2</a></li>
            <li><a href="/page2.3.html" data-toggle="tab">Page 2.3</a></li>
        </ul>
    </li>
    <li class="dropdown">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Page 3 <b class="caret"></b></a>
        <ul class="dropdown-menu">
            <li><a href="/page3.html" data-toggle="tab">Home</a></li>
            <li class="divider"></li>
            <li class="dropdown-submenu">
                <a href="/page3.2.html" data-toggle="tab">Page 3.2</a>
                <ul class="dropdown-menu">
                    <li><a href="/page3.2.1.html" data-toggle="tab">Page 3.2.1</a></li>
                    <li><a href="/page3.2.2.html" data-toggle="tab">Page 3.2.2</a></li>
                </ul>
            </li>
        </ul>
    </li>
    <li><a href="/page4.html" data-toggle="tab">Page 4</a></li>
</ul>

<script>
window.onload=function (e) {
    e.preventDefault();
    $('#supernav a[href="<?=$_SERVER["REQUEST_URI"];?>"]').tab('show');
};
</script>

Here are a couple URI examples:

http://abc.com/page1.html
http://abc.com/page2.3.html
http://abc.com/page3.2.2.html

Can anyone point me to a good example of how to accomplish this or am I just asking too much from this component?

NOTE: I've preloaded all the bootstrap and jquery resources in my header.

like image 389
Vince Avatar asked Jun 19 '13 19:06

Vince


4 Answers

I'm a little late to the party but just came across this post and I figured I'd add my extra 2 cents...

Basically, the best method I've found to set the active bootstrap's tab/pill is by using Javascript/jQuery to match the current url to the href of the active link.

So if your menu is set up as the following:

<ul class="nav nav-tabs">
    <li><a href="/page1.html" data-toggle="tab">Page 1</a></li>
    <li><a href="/page2.html" data-toggle="tab">Page 2</a></li>
</ul>

Your jQuery will be:

$(document).ready(function() {

    $('.nav-tabs a[href="'+location.href+'"]').parents('li').addClass('active');

});

This assumes absoulte path for the link's href, but that could be easily overriden by something like:

$(document).ready(function() {

    var url_parts = location.href.split('/');

    var last_segment = url_parts[url_parts.length-1];

    $('.nav-tabs a[href="' + last_segment + '"]').parents('li').addClass('active');

  });

Hope this helps somebody in the universe! :)

Cheers!

like image 78
dev7 Avatar answered Nov 03 '22 00:11

dev7


I've solved my own problem, here is a recap of the goal and what it took to accomplish.

Goals:

  1. I wanted to use the bootstrap nav-tabs component for my navigation bar because I liked the look/feel of it better.
  2. I wanted to be able to set the 'active' class by parsing the incoming URI.
  3. I wanted sub-navigation to work as well.

New code based on first post:

<ul class="nav nav-tabs" id="supernav">
    <li id="page1"><a href="/page1.html"><i class="icon-home" style="margin-top:4px;"></i> Page 1</a></li>
    <li class="dropdown" id="page2">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Page 2 <b class="caret"></b></a>
        <ul class="dropdown-menu">
            <li id="page2_home"><a href="/page2.html">Home</a></li>
            <li class="divider"></li>
            <li id="page2_2"><a href="/page2.2.html">Page 2.2</a></li>
            <li id="page2_3"><a href="/page2.3.html">Page 2.3</a></li>
        </ul>
    </li>
    <li class="dropdown" id="page3">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Page 3 <b class="caret"></b></a>
        <ul class="dropdown-menu">
            <li id="page3_home"><a href="/page3.html">Home</a></li>
            <li class="divider"></li>
            <li class="dropdown-submenu" id="page3_2">
                <a href="/page3.2.html">Page 3.2</a>
                <ul class="dropdown-menu">
                    <li id="page3_2_1"><a href="/page3.2.1.html">Page 3.2.1</a></li>
                    <li id="page3_2_2"><a href="/page3.2.2.html">Page 3.2.2</a></li>
                </ul>
            </li>
        </ul>
    </li>
    <li id="page4"><a href="/page4.html">Page 4</a></li>
</ul>

Notice in the code above that there are no

class="active"

or

data-toggle="tab"

set anywhere.

Because I wanted to make my nav on a static template which is used as a header for all templates I couldn't add any dynamically generated code based on incoming URI's but it turns out not to be necessary.

I added the following Javascript code to bottom of each template a visitor calls to help tell the nav-list which items to be marked as 'active'.

I used this script at the bottom of my /page1.html

<script type="text/javascript">
window.onload=function () {
    $('#page1').addClass('active');
};
</script>

To set /page3.2.2.html as the active page and all the nav lvls above it I did this

<script type="text/javascript">
window.onload=function () {
    $('#page3').addClass('active');
    $('#page3_2').addClass('active');
    $('#page3_2_2').addClass('active');
};
</script>

Now when a user comes to my site the nav gets loaded from a static file and the rest of the page contains the dynamic JavaScript that sets what components I want set active.

I also found it necessary to make this one little modification to my custom css in order to make sure no line appeared under my 'active' tab, just a visual thing probably needed because of my font settings.

.nav-tabs > li { margin-bottom: -3px; }

I would have posted some SS's but my 'rep' isn't above 10 yet, ha ha ha. Hopefully this helps someone else, god help us all when version 3 of bootstrap comes out and we have to figure this all out again. 8^)P

like image 29
Vince Avatar answered Nov 02 '22 22:11

Vince


Tab is set active on the client-side, not on the server. This is because, usually all the contents of each tab are actually there already in the document on page load. Clicking on a tab simple hides one tab and then shows the tab having the id which the anchor element links to.

Here's what the simplest implementation of Bootstrap's tab looks like:

<!-- tab navigation -->
<ul class="nav nav-tabs">
    <li class="active">
        <a href="#tab1">Home</a>
    </li>
    <li><a href="#tab2">...</a></li>
    <li><a href="#tab3">...</a></li>
</ul>

<!-- tab contents are inside -->
<div class="tab-content">
    <!-- content of each tab is put inside a tab-pane or tab-pill -->
    <div class="tab-pane active" id="tab1">
        <p>content of tab 1</p>
    </div>
    <div class="tab-pane" id="tab2">
        <p>content of tab 2</p>
    </div>
    <div class="tab-pane" id="tab2">
        <p>content of tab 3</p>
    </div>
</div>

That's not all, you still need to activate tabbing using JS like this:

$('ul.nav.nav-tabs > li > a').click(function(e) {
    e.preventDefault();
    $(this).tab('show');
});

Based on how your question is constructed, I think you should go have a better look at what each Bootstrap component stands for, and try to understand what are their appropriate use-case.

If your aim was to show a specific tab in response to a request. Simply add the 'active' class to the div element that wraps its content.

And then make it show by doing this:

$('tab-pane active').tab('show');

Note: all you have to do is add active in the right place each time.

For you case specifically, the problem is in your jQuery. Here's the correct way to write it:

$('#supernav active').tab('show');
like image 31
Igwe Kalu Avatar answered Nov 03 '22 00:11

Igwe Kalu


I was facing similar problem while I had few page urls like : www.somedomain.com/pages/xyz/abc/samplepage.html

This code worked in my case like magic.

    $(document).ready(function() {
        var permalink_nodomain = window.location.pathname;
        $('.nav-tabs a[href="' + permalink_nodomain + '"]').parents('li').addClass('active');
    });

May be someone is still looking for this solution just like me :)

like image 28
Gouranga Tarafder Avatar answered Nov 03 '22 00:11

Gouranga Tarafder