javascripthtmltwitter-bootstrapcanjscanjs-routing

Location.hash returns empty string


I am currently using jQuery, Twitter Bootstrap and CanJS for my web application. I'm trying to implement routing with CanJS. I'm using Bootstrap's tab, and when I click on a tab, it was supposed to bring #tabSearch, #tabUser or #tabPermissions, but the hash is returned with an empty string. What am I doing wrong?

I´m using this to change the tabs:

     TabControl = can.Control.extend({}, {
        init: function (element, options) {
        element.find('a[href="' + options.defaultTab + '"]').tab('show');
        this.userSearch = null;
        this.userForm = null;
    }
    , 'a[data-toggle="tab"] show': function (e) {
        this.options.tabChangeCallback(e);
    }
});

     UserTab = new TabControl('#tabctrlUser', {
       defaultTab: '#tabSearch',
       tabChangeCallback: function (e) {

        if (e.context.hash == '#tabSearch') {                
            if (!this.userSearch) {
                this.userSearch = new FormUserQuery('#tabSearch', {});
            } 
        } else if (e.context.hash == '#tabUser') { 
            if (!this.userForm) {
                this.userForm = new FormUser('#tabUser', {});
            }
            this.userForm.renderView(currentUser);
        } else if (e.context.hash == '#tabPermissions') {                
            new FormPermissions('#tabPermissions', {});

        }
    }
});

Here is the HTML part:

<ul id="tabctrlUser" class="nav nav-tabs">
     <li><a href="#tabSearch"  data-toggle="tab">Pesquisar</a></li>
     <li><a href="#tabUser"  data-toggle="tab">Cadastrar/Alterar</a></li>
     <li><a href="#tabPermissions"  data-toggle="tab">Acessos</a></li>
</ul>
<div class="tab-content">
     <div class="tab-pane" id="tabSearch"></div>
     <div class="tab-pane" id="tabUser"></div>
     <div class="tab-pane" id="tabPermissions"></div>
</div>

Solution

  • You need to use can.route or can.Control.Route, the way you do it is complicated take a look at this question Also there's 2 good articles about routing

    look at this gist

    http://jsfiddle.net/Z9Cv5/2/light/

    var HistoryTabs = can.Control({
      init: function( el ) {
    
        // hide all tabs
        var tab = this.tab;
        this.element.children( 'li' ).each(function() {
          tab( $( this ) ).hide();
        });
    
        // activate the first tab
        var active = can.route.attr(this.options.attr);
        this.activate(active);
      },
      "{can.route} {attr}" : function(route, ev, newVal, oldVal){
        this.activate(newVal, oldVal)
      },
      // helper function finds the tab for a given li
      tab: function( li ) {
        return $( li.find( 'a' ).attr( 'href' ) );
      },
      // helper function finds li for a given id
      button : function(id){
        // if nothing is active, activate the first
        return id ? this.element.find("a[href=#"+id+"]").parent()  : 
                    this.element.children( 'li:first' );
      },
      // activates 
      activate: function( active, oldActive ){
        // deactivate the old active
        var oldButton = this.button(oldActive).removeClass('active');
        this.tab(oldButton).hide();
        // activate new
        var newButton = this.button(active).addClass('active');
        this.tab(newButton).show();
      },
      "li click" : function(el, ev){
        // prevent the default setting
        ev.preventDefault();
        // update the route data
        can.route.attr(this.options.attr, this.tab(el)[0].id)
      }
    });
    
    // configure routes
    can.route(":component",{
      component: "model",
      person: "mihael"
    });
    
    can.route(":component/:person",{
      component: "model",
      person: "mihael"
    });
    
    // adds the controller to the element
    new HistoryTabs( '#components',{attr: 'component'});
    new HistoryTabs( '#people',{attr: 'person'});