1

I have a view with two tabs. When clicking on a tab, I want to:

  1. show the tab
  2. change the hash to #view/tabName

If the hash change between #view/tab1 and #view/tab2, the route won't trigger, but the view show tab2. If the hash changed from #anotherView to #view/tabName, the route will trigger, and render the view with initial tab tabName.

To summary, when the hash changes between hashes with the same prefix #view, the view will handle the event, else the router.

Here's my current code.

// router.js
define('router', [
    'jquery'
    , 'underscore'
    , 'backbone'
    , 'SomeView'

], function (
    $, _, backbone, SomeView
) {
    var router;

    router = backbone.Router.extend({
        routes: {
            'some-view': someView
            , 'some-view/:tab': someView
        }
        , initialize: function () {

        }
        , someView: function (tab) {
            var view; 
            view = new SomeView(tab);
            view.on('router:changeTab', function (tab) {
                that.navigate('some-view/' + tab);
            });


        }
    });
    return router;
});

// someView.js
define('SomeView', [
    'jquery'
    , 'underscore'
    , 'backbone'
], function (
    $, _, backbone
) {
    var SomeView;

    SomeView = backbone.View.extend({

        initialize: function (options) {
            this.tab = options.tab;

        }
        , render: function (callback) {

            // show the initial tab if given
            if (this.tab) {
                setTimeout(function () {
                    that.$el.find('[href="#' + that.tab + '-tab"]').click();
                }, 0);
            }

            return this;
        }
        , events: {
            , 'click .nav-tabs>li>a': 'showTab' // enable tabs
        }

        , showTab: function (e) {
            var that, tab, tabs;
            that = this;
            e.preventDefault();
            $(this).tab('show');  // I'm using bootstrap tab plugin
            // update hash
            tab = $(e.currentTarget).attr('href').split('-')[0].split('#')[1];
            that.trigger('router:changeTab', tab);
            // What I didn't know is how to prevent the handler from being 
            // invoked when the user press backward/forward button on the browser,
            // and let this view handle it (show the corresponding tab). 
        }
    return SomeView;
});
Trantor Liu
  • 8,770
  • 8
  • 44
  • 64
  • So how do you switch between tabs any javascript plugins, Yes!! then hook to the event(`TabChange`) and the view responds by changing the hash without invoking the router callback else follow this methodology view changes the url hash, router subscribes to the tab change hash , invokes a event on the collection/model displayed in these tabs so that views can subscribe and act accordingly – Deeptechtons Aug 17 '12 at 05:08
  • so if you don't want to trigge a route you should use the navigate method with the options specifying not to invoke callback http://backbonejs.org/#Router-navigate – Deeptechtons Aug 17 '12 at 07:24
  • @Deeptechtons: If I set `replace`, there won't be history of navigating through tabs. But what I want is there still histories, but when user click backward/forward buttons on browser, the handler is depends on the previous page. If the previous page is **some-view**, then keep the user in the same view without reloading it, and just switch the tab. If the previous view is not **some-view**, that the router handle, which will render **some-view** with/without initial tab. – Trantor Liu Aug 17 '12 at 07:34

1 Answers1

0

You can use the dynamic routing, where you may specify routes like:

routes : {
  "view/:tab_name" : "show_tab",
  "otherRoutes" : "other_methods"
},

show_tab : function(tab_name) {
  // render tab based on the parameter you receive
}

so if address bar contains the url #view/tab1 then you'l receive 'tab1' as tab_name parameter in the show_tab method and same for #view/tab2 also.

You can refer this link by Thomas Davis to know more about backbone routers.

Cyclone
  • 1,580
  • 1
  • 8
  • 14