define([ 'dojo/_base/declare', 'dojo/hash', 'dojo/topic', './Content', './Page', './Path' ],function(declare,hash,topic,Content,Page,Path){ var Router = declare(null,{ _started: false, _routes: null, _previousHash: null, constructor: function() { this._routes = []; }, startup: function() { if ( this._started ) { return; } if ( !Content._started ) { Content.startup(); } this._started = true; var self = this; if ( hash() === "" ) { hash(Path.getDefault()); } this._handlePathChange(hash()); topic.subscribe("/dojo/hashchange", function(){ self._handlePathChange.apply(self,arguments); }); }, register: function(route) { if ( this._started ) { console.warn('Registering routes after startup() is called is discouraged.'); } var callback = this._normalizeCallback(route); if ( callback ) { if ( route.path ) { route.callback = callback; route.path = new Path(route.path); this._routes.push(route); } else { this._defaultCallback = callback; } } else { console.warn("Route "+(route.path||"default")+" has no action."); } }, _normalizeCallback: function(route) { var self = this; var callback = null; if ( route.callback ) { callback = function(params){ Content.set(route.callback(params)); }; } else if ( route.redirect ) { callback = function(params){ self.go(route.redirect); }; } else if ( route.constructor ) { callback = function(params){ Content.set( new route.constructor(params) ); }; } return callback; }, _handlePathChange: function(newHash) { if ( this._previousHash === newHash ) { return; } this._previousHash = newHash; for (var i = this._routes.length-1; i >= 0; i--) { var route = this._routes[i]; var params = null; if ((params = route.path.match(newHash)) !== null) { try { route.callback(params); } catch(err) { console.error("Page change failed.",err); } return; } } try { this._defaultCallback(); } catch(err) { console.error("Default page failed.",err); } }, go: function(path,args) { if ( !this._started ) { return; } var newHash = Path.format(path,args); this._handlePathChange(newHash); hash(newHash); }, _defaultCallback: function() { Content.set(new Page({ templateString: "