Login Register

more extensive Back Button example

Judging from the forums, people have gotten the back button feature to work. I'm not one of them. For example, can you go back and forth between tabs in a TabContainer if you addToHistory on each selectedChild event.

I've tried using addToHistory on each selectedChild event, and can save the id's of a stack of selected tabs and go back and forth in the history with the callbacks (after selecting a number of tabs) without changing the selected tab. Changing the tab based on the history seems to mess up the stack.

I'm calling dojo.back.init() in a script in the body of the main page, setting dojoIframeHistoryUrl in djConfig to the iframe_history.html on the same server, and calling setInitialState at the very beginning.

Does someone have a more complex example than what is in the test for the back button module that they would be willing to share. I'm missing something fundamental.

Partial example

Hi,

I haven't yet hooked up the initial back button state from the server, but I have hooked up history for navigating through tabs in a tabcontainer. I'm not using an iframe, either... just the dojo.back behavior with URL fragments.

Here's what my code looks like:

auriga.Main = {
                uihistory: [], // array stack to contain history items
                uipos: 0, // index (1-based) of current page in uihistory
                inBack: false, // flag to indicate whether we're opening a tab due to back button, or new link

                uicontroller: function(args){
                                // itemid is used to uniquely identify a tab
                                var itemid = args.itemid ? 'tab_'+args.itemid: 'tab_'+ args.module+act;
                                var uiargs = dojo.clone(args); // attach a copy to any new node we create
                                // args contains everything necessary to re-open a closed tab, or switch to it if it's still open
                      // snip processing
                                var t = dijit.byId(itemid);
                                if (t == null){
                                                t=document.createElement('div');
                                                t.id = itemid;
                                                t = new dijit.layout.ContentPane( { href:'dispatcher.php?view='+view+'&module_id='+module_id+'&'+dojo.objectToQuery(args), id:itemid, closable:true,title:title }, t);
                                                dijit.byId('main_tab').addChild(t);
                                                t.uiargs = uiargs; // pass through for use in history
                                                t.closeHndl = dojo.connect(t,'onClose',t,function(){
                                                                dojo.disconnect(this.closeHndl);
                                                                delete this.uiargs; // not sure if this is necessary
                                                });
                                }
                                dijit.byId('main_tab').selectChild(t);
                               
                },
               
                handleBack: function(dir){
                                //console.log(dir,' clicked', auriga.Main);
                                if (dir == 'forward'){
                                                auriga.Main.uipos++;
                                } else {
                                                auriga.Main.uipos--;
                                }
                                var args = auriga.Main.uihistory[auriga.Main.uipos -1];
                                auriga.Main.inBack = true; // set this so that we don't add to history
                                auriga.Main.uicontroller(dojo.clone(args));
                },
 
                // and now the real meat:
                tabHistory: function(tab){
                                if (this.inBack){ // reset for next action, and skip adding history
                                                this.inBack = false;
                                } else {
                                                dojo.back.addToHistory({handle: auriga.Main.handleBack,changeUrl:tab.id});
                                                while (this.uipos < this.uihistory.length){
                                                                this.uihistory.pop(); // for new tabs after backing up, get rid of future
                                                }
                                                auriga.Main.uihistory.push(dojo.clone(tab.uiargs));
                                                auriga.Main.uipos++;
                                }
                                document.title="Project Auriga: "+tab.title; // for bonus points, change window title
                }
}

// now hook it up:
dojo.addOnLoad( function(){
       // tab container publishes a topic when you click a tab... this listens to the tab container with an id of 'main_tab':
       dojo.subscribe('main_tab-selectChild',auriga.Main, auriga.Main.tabHistory);
       dojo.back.setInitialState({handle: auriga.Main.handleBack}); // TODO: add an object representing the original tab
}
);

You can this in more context here: https://baker.freelock.com/svn/auriga/trunk/public_html/auriga/Main.js

Hope this helps,
--
John Locke
http://www.freelock.com

problem with left over callbacks

Using your code as a hint, I was able to get my somewhat simplistic code to work (just using changeUrl's and a selectChild handler). I'm not using iframes either. Navigating back and forth in the application works great.

I have one problem. I create tabs dynamically on user login, and destroy them on user logout. There can be left over items in historyStack and forwardStack from navigating through the tabs using the back and forward buttons. Upon logout, the back callbacks have to be called first before going to the first page before my application, and the forward stack is left over, with the accompanying problems.

I don't see anything in back.js for removing something from the history, or whether that is a possibility.