15

I want to have a tab-navigation in my jQuery Mobile project. I know I can use the data-role 'navbar' but I only want to change the content below that navbar without swiping to a new page. So far I could only have several different pages with the same navbar linking to each other but that's not what I want.

Can anyone help me?

Thank you in advance

Reporter
  • 3,897
  • 5
  • 33
  • 47
Matteo
  • 151
  • 1
  • 1
  • 3

6 Answers6

32

You can use the jQuery Mobile navbar styling but use your own click-handler so instead of changing pages the click will just hide/show the proper content on the same page.

HTML

<div data-role="navbar">
    <ul>
        <li><a href="#" data-href="a">One</a></li>
        <li><a href="#" data-href="b">Two</a></li>
    </ul>
</div><!-- /navbar -->
<div class="content_div">onLoad Content</div>
<div id="a" class="content_div">Some 'A' Content</div>
<div id="b" class="content_div">Some 'B' Content</div>

JAVASCRIPT

$(document).delegate('[data-role="navbar"] a', 'click', function () {
    $(this).addClass('ui-btn-active');
    $('.content_div').hide();
    $('#' + $(this).attr('data-href')).show();
    return false;//stop default behavior of link
});

CSS

.content_div {
    display: none;
}
.content_div:first-child {
    display: block;
}

Here is a jsfiddle of the above code: http://jsfiddle.net/3RJuX/

NOTE:

  • Each of the links in the navbar have a "data-href" attribute set to the id of the div (or whatever container you want to use) that will be displayed.

Update

After 1 year I came back to this answer and noticed that the delegated event handler selector can be optimized a bit to utilize a class rather than an attribute (which is a lot faster of a lookup):

$(document).delegate('.ui-navbar a', 'click', function () {
    $(this).addClass('ui-btn-active');
    $('.content_div').hide();
    $('#' + $(this).attr('data-href')).show();
});

Update

This code can be made to be more modular by using relative selectors rather than absolute ones (like $('.content_div'), as this will select all matching elements in the DOM rather than just ones relative to the button clicked).

//same selector here
$(document).delegate('.ui-navbar ul li > a', 'click', function () {

    //un-highlight and highlight only the buttons in the same navbar widget
    $(this).closest('.ui-navbar').find('a').removeClass('ui-navbar-btn-active');

    //this bit is the same, you could chain it off of the last call by using two `.end()`s
    $(this).addClass('ui-navbar-btn-active');

    //this starts the same but then only selects the sibling `.content_div` elements to hide rather than all in the DOM
    $('#' + $(this).attr('data-href')).show().siblings('.content_div').hide();
});​

This allows you to nest tabs and/or have multiple sets of tabs on a pages or pseudo-pages.

Some documentation for the "relative selectors" used:

Here was an example: http://jsfiddle.net/Cfbjv/25/ (It's offline now)

RzR
  • 3,068
  • 29
  • 26
Jasper
  • 75,717
  • 14
  • 151
  • 146
  • Thanks for this - had exactly the same problem earlier this afternoon and was trying to work it out when I stumbled across this post which no doubt has saved me hours - +1 from me – Jon Clements Jul 13 '12 at 22:59
  • @Jasper, any chance you'd give a hand for nested tabs? I managed to get the main tabs showing their content just fine with `.ui-navbar ul li > a` on the firsts two line but once i click a nested tab it "shuts all down" due to the `$('.content_div').hide();`. Thanks. – kevin Oct 18 '12 at 17:13
  • @kevin If you setup a JSFiddle of your current code I'll take a look. – Jasper Oct 18 '12 at 17:39
  • @kevin You can make the event handler code relative to the element clicked by using relative selectors like `.closest()` and `.siblings()`. See what I came up with here: http://jsfiddle.net/Cfbjv/25/ – Jasper Oct 19 '12 at 02:01
  • @Jasper Thanks a lot man! I had an error with chrome cos in the copy/paste process there was a hidden character at the end that was bugging it all (Uncaught SyntaxError: Unexpected token ILLEGAL). Also i've changed the js to use the `on` method as of jQuery 1.7+ http://jsfiddle.net/kevinch/Cfbjv/30/ All fine now. Thanks again. – kevin Oct 19 '12 at 14:31
  • @Jasper: Thanks a lot ! nice answer – V-Xtreme Dec 25 '15 at 12:00
4

UPDATE: Check out my jsfiddle at http://jsfiddle.net/ryanhaney/eLENj/

I just spent some time figuring this out, so I thought I would answer this. Note I am using multi-page single file, YMMV.

<div data-role="footer" data-position="fixed">
    <div data-role="navbar">
        <ul>
            <li><a href="#page-1" data-role="tab" data-icon="grid">Page 1</a></li>
            <li><a href="#page-2" data-role="tab" data-icon="grid">Page 2</a></li>
            <li><a href="#page-3" data-role="tab" data-icon="grid">Page 3</a></li>
        </ul>
    </div>
</div>

$("div[data-role=page]").bind("pagebeforeshow", function () {
    // prevents a jumping "fixed" navbar
    $.mobile.silentScroll(0);
});

$("a[data-role=tab]").each(function () {
        // bind to click of each anchor
        var anchor = $(this);
        anchor.bind("click", function () {
            // change the page, optionally with transitions
            // but DON'T navigate...
            $.mobile.changePage(anchor.attr("href"), {
                transition: "none",
                changeHash: false
        });

        // cancel the click event
        return false;
    });
});
Ryan Haney
  • 500
  • 1
  • 6
  • 9
  • What if you wanted to display a particular tab's page based on what day it is? Also, this example loses the 'active' tab after a few tab clicks and when using the back button. Also, when first loaded in Firefox it shows the navbar in the middle of the page for a second when you click a tab, but only for a second. And after a couple of clicks it doesn't do that anymore – Justin White Mar 07 '12 at 02:41
  • The following code will change to page 2. As for the navbar issue, have you tried JQM 1.1 RC1? $.mobile.changePage("#page-2", { transition: "none", changeHash: false }); – Ryan Haney Mar 07 '12 at 07:23
2

@Mike Bartlett

I struggled with this myself but after breaking Jasper's code down it looks like there is a slight nuance from his posted code and that on the jsfiddle page.

Where he has posted

$(document).delegate('[data-role="navbar"] a', 'click', function () {
$(this).addClass('ui-btn-active');
$('.content_div').hide();
$('#' + $(this).attr('data-href')).show(); });

I found it useful to change the last line to simply call whatever content you set the "data-href" value to be in your navbar.

$('div[data-role="navbar"] a').live('click', function () {
    $(this).addClass('ui-btn-active');
    $('div.content_div').hide();
    $($(this).attr('data-href')).show();
  });

my navbar html then reads

<div data-role="navbar">
<ul>
    <li><a href="#" data-href="#a">One</a></li>
    <li><a href="#" data-href="#b">Two</a></li>
</ul>

Which is pretty much the same as his but for some reason I got no "error loading page" message. Hope that helps...

1

Please refers this below link for all kind of nav bar in jquery

http://jquerymobile.com/demos/1.0rc2/docs/toolbars/docs-navbar.html

<div data-role="navbar">
   <ul>
    <li><a href="a.html" class="ui-btn-active">One</a></li>
    <li><a href="b.html">Two</a></li>
   </ul>
</div>

thanks

Rajarshi Das
  • 11,778
  • 6
  • 46
  • 74
1

I noticed that the question was asked four years ago, so i'm not sure whether the Tab widget were available with JQ Mobile at that time. anyway i'm a guy from 2015

the awesome solution that i use as below with Jquery Mobile 1.4.5

<div data-role="tabs" id="tabs">
  <div data-role="navbar">
    <ul>
      <li><a href="#one" data-ajax="false">one</a></li>
      <li><a href="#two" data-ajax="false">two</a></li>
      <li><a href="ajax-content-ignore.html" data-ajax="false">three</a></li>
    </ul>
  </div>
  <div id="one" class="ui-body-d ui-content">
    <h1>First tab contents</h1>
  </div>
  <div id="two">
    <ul data-role="listview" data-inset="true">
        <li><a href="#">Acura</a></li>
        <li><a href="#">Audi</a></li>
        <li><a href="#">BMW</a></li>
        <li><a href="#">Cadillac</a></li>
        <li><a href="#">Ferrari</a></li>
    </ul>
  </div>
</div>
rashidnk
  • 4,096
  • 2
  • 22
  • 32
0

I liked @Ryan-Haney's answer, but thought I'd add my own rough draft in, if anyone can find a more efficient way of doing this, then please add a comment.. thanks

I did it this way because I have a bunch of "include" files that get loaded into the DOM at runtime, so I couldn't hard-code that the n-th tab is highlighted/active for each page like Ryan could. I also do have the luxury of having only a single tabbar in my app.

$(document).delegate('.ui-navbar a', 'tap', function ()
{
  $('.ui-navbar').find('li').find('a').removeClass('ui-btn-active');
  $('.ui-navbar').find('li:nth-child(' + ($(this).parent().index() + 1) + ')').find('a').addClass('ui-btn-active');
});
Ads
  • 2,084
  • 2
  • 24
  • 34