UNPKG

dojox

Version:

Dojo eXtensions, a rollup of many useful sub-projects and varying states of maturity – from very stable and robust, to alpha and experimental. See individual projects contain README files for details.

128 lines (110 loc) 4.57 kB
define(["dojo/_base/lang", "dojo/_base/declare", "dojo/on", "../Controller", "../utils/hash", "dojo/topic"], function(lang, declare, on, Controller, hash, topic){ // module: // dojox/app/controllers/History // summary: // Bind "app-domNode" event on dojox/app application instance. // Bind "startTransition" event on dojox/app application domNode. // Bind "popstate" event on window object. // Maintain history by HTML5 "pushState" method and "popstate" event. return declare("dojox.app.controllers.History", Controller, { // _currentPosition: Integer // Persistent variable which indicates the current position/index in the history // (so as to be able to figure out whether the popState event was triggerd by // a backward or forward action). _currentPosition: 0, // currentState: Object // Current state currentState: {}, constructor: function(){ // summary: // Bind "app-domNode" event on dojox/app application instance. // Bind "startTransition" event on dojox/app application domNode. // Bind "popstate" event on window object. // this.events = { "app-domNode": this.onDomNodeChange }; if(this.app.domNode){ this.onDomNodeChange({oldNode: null, newNode: this.app.domNode}); } this.bind(window, "popstate", lang.hitch(this, this.onPopState)); }, onDomNodeChange: function(evt){ if(evt.oldNode != null){ this.unbind(evt.oldNode, "startTransition"); } this.bind(evt.newNode, "startTransition", lang.hitch(this, this.onStartTransition)); }, onStartTransition: function(evt){ // summary: // Response to dojox/app "startTransition" event. // // example: // Use "dojox/mobile/TransitionEvent" to trigger "startTransition" event, and this function will response the event. For example: // | var transOpts = { // | title:"List", // | target:"items,list", // | url: "#items,list", // | params: {"param1":"p1value"} // | }; // | new TransitionEvent(domNode, transOpts, e).dispatch(); // // evt: Object // Transition options parameter var currentHash = window.location.hash; var currentView = hash.getTarget(currentHash, this.app.defaultView); var currentParams = hash.getParams(currentHash); var _detail = lang.clone(evt.detail); _detail.target = _detail.title = currentView; _detail.url = currentHash; _detail.params = currentParams; _detail.id = this._currentPosition; // Create initial state if necessary if(history.length == 1){ history.pushState(_detail, _detail.href, currentHash); } // Update the current state _detail.bwdTransition = _detail.transition; lang.mixin(this.currentState, _detail); history.replaceState(this.currentState, this.currentState.href, currentHash); // Create a new "current state" history entry this._currentPosition += 1; evt.detail.id = this._currentPosition; var newHash = evt.detail.url || "#" + evt.detail.target; if(evt.detail.params){ newHash = hash.buildWithParams(newHash, evt.detail.params); } evt.detail.fwdTransition = evt.detail.transition; history.pushState(evt.detail, evt.detail.href, newHash); this.currentState = lang.clone(evt.detail); // Finally: Publish pushState topic topic.publish("/app/history/pushState", evt.detail.target); }, onPopState: function(evt){ // summary: // Response to dojox/app "popstate" event. // // evt: Object // Transition options parameter // Clean browser's cache and refresh the current page will trigger popState event, // but in this situation the application has not started and throws an error. // So we need to check application status, if application not STARTED, do nothing. if((this.app.getStatus() !== this.app.lifecycle.STARTED) || !evt.state ){ return; } // Get direction of navigation and update _currentPosition accordingly var backward = evt.state.id < this._currentPosition; backward ? this._currentPosition -= 1 : this._currentPosition += 1; // Publish popState topic and transition to the target view. Important: Use correct transition. // Reverse transitionDir only if the user navigates backwards. var opts = lang.mixin({reverse: backward ? true : false}, evt.state); opts.transition = backward ? opts.bwdTransition : opts.fwdTransition; this.app.emit("app-transition", { viewId: evt.state.target, opts: opts }); topic.publish("/app/history/popState", evt.state.target); } }); });