summaryrefslogtreecommitdiff
path: root/lib/dojo/router
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2013-03-18 10:26:24 +0400
committerAndrew Dolgov <[email protected]>2013-03-18 10:26:26 +0400
commitf0cfe83e3725f9a3928da97a6e3085e79cb25309 (patch)
tree4b0af188defaa807c7bc6ff3a101b41c9166c463 /lib/dojo/router
parent9a2885da170ffd64358b99194095851a2d09c1b6 (diff)
upgrade dojo to 1.8.3 (refs #570)
Diffstat (limited to 'lib/dojo/router')
-rw-r--r--lib/dojo/router/RouterBase.js8
-rw-r--r--lib/dojo/router/RouterBase.js.uncompressed.js350
2 files changed, 358 insertions, 0 deletions
diff --git a/lib/dojo/router/RouterBase.js b/lib/dojo/router/RouterBase.js
new file mode 100644
index 000000000..3862884a2
--- /dev/null
+++ b/lib/dojo/router/RouterBase.js
@@ -0,0 +1,8 @@
+/*
+ Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+//>>built
+define("dojo/router/RouterBase",["dojo/_base/declare","dojo/hash","dojo/topic"],function(_1,_2,_3){var _4;if(String.prototype.trim){_4=function(_5){return _5.trim();};}else{_4=function(_6){return _6.replace(/^\s\s*/,"").replace(/\s\s*$/,"");};}function _7(_8,_9,_a){var _b,_c,_d,_e,i,l;_b=this.callbackQueue;_c=false;_d=false;_e={stopImmediatePropagation:function(){_c=true;},preventDefault:function(){_d=true;},oldPath:_9,newPath:_a,params:_8};for(i=0,l=_b.length;i<l;++i){if(!_c){_b[i](_e);}}return !_d;};var _f=_1(null,{_routes:null,_routeIndex:null,_started:false,_currentPath:"",idMatch:/:(\w[\w\d]*)/g,idReplacement:"([^\\/]+)",globMatch:/\*(\w[\w\d]*)/,globReplacement:"(.+)",constructor:function(_10){this._routes=[];this._routeIndex={};for(var i in _10){if(_10.hasOwnProperty(i)){this[i]=_10[i];}}},register:function(_11,_12){return this._registerRoute(_11,_12);},registerBefore:function(_13,_14){return this._registerRoute(_13,_14,true);},go:function(_15,_16){var _17;_15=_4(_15);_17=this._handlePathChange(_15);if(_17){_2(_15,_16);}return _17;},startup:function(){if(this._started){return;}var _18=this;this._started=true;this._handlePathChange(_2());_3.subscribe("/dojo/hashchange",function(){_18._handlePathChange.apply(_18,arguments);});},_handlePathChange:function(_19){var i,j,li,lj,_1a,_1b,_1c,_1d,_1e,_1f=this._routes,_20=this._currentPath;if(!this._started||_19===_20){return _1c;}_1c=true;for(i=0,li=_1f.length;i<li;++i){_1a=_1f[i];_1b=_1a.route.exec(_19);if(_1b){if(_1a.parameterNames){_1d=_1a.parameterNames;_1e={};for(j=0,lj=_1d.length;j<lj;++j){_1e[_1d[j]]=_1b[j+1];}}else{_1e=_1b.slice(1);}_1c=_1a.fire(_1e,_20,_19);}}if(_1c){this._currentPath=_19;}return _1c;},_convertRouteToRegExp:function(_21){_21=_21.replace(this.idMatch,this.idReplacement);_21=_21.replace(this.globMatch,this.globReplacement);_21="^"+_21+"$";return new RegExp(_21);},_getParameterNames:function(_22){var _23=this.idMatch,_24=this.globMatch,_25=[],_26;_23.lastIndex=0;while((_26=_23.exec(_22))!==null){_25.push(_26[1]);}if((_26=_24.exec(_22))!==null){_25.push(_26[1]);}return _25.length>0?_25:null;},_indexRoutes:function(){var i,l,_27,_28,_29=this._routes;_28=this._routeIndex={};for(i=0,l=_29.length;i<l;++i){_27=_29[i];_28[_27.route]=i;}},_registerRoute:function(_2a,_2b,_2c){var _2d,_2e,_2f,_30,_31,_32=this,_33=this._routes,_34=this._routeIndex;_2d=this._routeIndex[_2a];_2e=typeof _2d!=="undefined";if(_2e){_2f=_33[_2d];}if(!_2f){_2f={route:_2a,callbackQueue:[],fire:_7};}_30=_2f.callbackQueue;if(typeof _2a=="string"){_2f.parameterNames=this._getParameterNames(_2a);_2f.route=this._convertRouteToRegExp(_2a);}if(_2c){_30.unshift(_2b);}else{_30.push(_2b);}if(!_2e){_2d=_33.length;_34[_2a]=_2d;_33.push(_2f);}_31=false;return {remove:function(){var i,l;if(_31){return;}for(i=0,l=_30.length;i<l;++i){if(_30[i]===_2b){_30.splice(i,1);}}if(_30.length===0){_33.splice(_2d,1);_32._indexRoutes();}_31=true;},register:function(_35,_36){return _32.register(_2a,_35,_36);}};}});return _f;}); \ No newline at end of file
diff --git a/lib/dojo/router/RouterBase.js.uncompressed.js b/lib/dojo/router/RouterBase.js.uncompressed.js
new file mode 100644
index 000000000..821d74499
--- /dev/null
+++ b/lib/dojo/router/RouterBase.js.uncompressed.js
@@ -0,0 +1,350 @@
+define("dojo/router/RouterBase", [
+ "dojo/_base/declare",
+ "dojo/hash",
+ "dojo/topic"
+], function(declare, hash, topic){
+
+ // module:
+ // dojo/router/RouterBase
+
+ // Creating a basic trim to avoid needing the full dojo/string module
+ // similarly to dojo/_base/lang's trim
+ var trim;
+ if(String.prototype.trim){
+ trim = function(str){ return str.trim(); };
+ }else{
+ trim = function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };
+ }
+
+ // Firing of routes on the route object is always the same,
+ // no clean way to expose this on the prototype since it's for the
+ // internal router objects.
+ function fireRoute(params, currentPath, newPath){
+ var queue, isStopped, isPrevented, eventObj, i, l;
+
+ queue = this.callbackQueue;
+ isStopped = false;
+ isPrevented = false;
+ eventObj = {
+ stopImmediatePropagation: function(){ isStopped = true; },
+ preventDefault: function(){ isPrevented = true; },
+ oldPath: currentPath,
+ newPath: newPath,
+ params: params
+ };
+
+ for(i=0, l=queue.length; i<l; ++i){
+ if(!isStopped){
+ queue[i](eventObj);
+ }
+ }
+
+ return !isPrevented;
+ }
+
+ // Our actual class-like object
+ var RouterBase = declare(null, {
+ // summary:
+ // A module that allows one to easily map hash-based structures into
+ // callbacks. The router module is a singleton, offering one central
+ // point for all registrations of this type.
+ // example:
+ // | var router = new RouterBase({});
+ // | router.register("/widgets/:id", function(evt){
+ // | // If "/widgets/3" was matched,
+ // | // evt.params.id === "3"
+ // | xhr.get({
+ // | url: "/some/path/" + evt.params.id,
+ // | load: function(data){
+ // | // ...
+ // | }
+ // | });
+ // | });
+
+ _routes: null,
+ _routeIndex: null,
+ _started: false,
+ _currentPath: "",
+
+ idMatch: /:(\w[\w\d]*)/g,
+ idReplacement: "([^\\/]+)",
+ globMatch: /\*(\w[\w\d]*)/,
+ globReplacement: "(.+)",
+
+ constructor: function(kwArgs){
+ // A couple of safety initializations
+ this._routes = [];
+ this._routeIndex = {};
+
+ // Simple constructor-style "Decorate myself all over" for now
+ for(var i in kwArgs){
+ if(kwArgs.hasOwnProperty(i)){
+ this[i] = kwArgs[i];
+ }
+ }
+ },
+
+ register: function(/*String|RegExp*/ route, /*Function*/ callback){
+ // summary:
+ // Registers a route to a handling callback
+ // description:
+ // Given either a string or a regular expression, the router
+ // will monitor the page's hash and respond to changes that
+ // match the string or regex as provided.
+ //
+ // When provided a regex for the route:
+ //
+ // - Matching is performed, and the resulting capture groups
+ // are passed through to the callback as an array.
+ //
+ // When provided a string for the route:
+ //
+ // - The string is parsed as a URL-like structure, like
+ // "/foo/bar"
+ // - If any portions of that URL are prefixed with a colon
+ // (:), they will be parsed out and provided to the callback
+ // as properties of an object.
+ // - If the last piece of the URL-like structure is prefixed
+ // with a star (*) instead of a colon, it will be replaced in
+ // the resulting regex with a greedy (.+) match and
+ // anything remaining on the hash will be provided as a
+ // property on the object passed into the callback. Think of
+ // it like a basic means of globbing the end of a route.
+ // example:
+ // | router.register("/foo/:bar/*baz", function(object){
+ // | // If the hash was "/foo/abc/def/ghi",
+ // | // object.bar === "abc"
+ // | // object.baz === "def/ghi"
+ // | });
+ // returns: Object
+ // A plain JavaScript object to be used as a handle for
+ // either removing this specific callback's registration, as
+ // well as to add new callbacks with the same route initially
+ // used.
+ // route: String|RegExp
+ // A string or regular expression which will be used when
+ // monitoring hash changes.
+ // callback: Function
+ // When the hash matches a pattern as described in the route,
+ // this callback will be executed. It will receive an event
+ // object that will have several properties:
+ //
+ // - params: Either an array or object of properties pulled
+ // from the new hash
+ // - oldPath: The hash in its state before the change
+ // - newPath: The new hash being shifted to
+ // - preventDefault: A method that will stop hash changes
+ // from being actually applied to the active hash. This only
+ // works if the hash change was initiated using `router.go`,
+ // as changes initiated more directly to the location.hash
+ // property will already be in place
+ // - stopImmediatePropagation: When called, will stop any
+ // further bound callbacks on this particular route from
+ // being executed. If two distinct routes are bound that are
+ // different, but both happen to match the current hash in
+ // some way, this will *not* keep other routes from receiving
+ // notice of the change.
+
+ return this._registerRoute(route, callback);
+ },
+
+ registerBefore: function(/*String|RegExp*/ route, /*Function*/ callback){
+ // summary:
+ // Registers a route to a handling callback, except before
+ // any previously registered callbacks
+ // description:
+ // Much like the `register` method, `registerBefore` allows
+ // us to register route callbacks to happen before any
+ // previously registered callbacks. See the documentation for
+ // `register` for more details and examples.
+
+ return this._registerRoute(route, callback, true);
+ },
+
+ go: function(path, replace){
+ // summary:
+ // A simple pass-through to make changing the hash easy,
+ // without having to require dojo/hash directly. It also
+ // synchronously fires off any routes that match.
+ // example:
+ // | router.go("/foo/bar");
+
+ var applyChange;
+
+ path = trim(path);
+ applyChange = this._handlePathChange(path);
+
+ if(applyChange){
+ hash(path, replace);
+ }
+
+ return applyChange;
+ },
+
+ startup: function(){
+ // summary:
+ // This method must be called to activate the router. Until
+ // startup is called, no hash changes will trigger route
+ // callbacks.
+
+ if(this._started){ return; }
+
+ var self = this;
+
+ this._started = true;
+ this._handlePathChange(hash());
+ topic.subscribe("/dojo/hashchange", function(){
+ // No need to load all of lang for just this
+ self._handlePathChange.apply(self, arguments);
+ });
+ },
+
+ _handlePathChange: function(newPath){
+ var i, j, li, lj, routeObj, result,
+ allowChange, parameterNames, params,
+ routes = this._routes,
+ currentPath = this._currentPath;
+
+ if(!this._started || newPath === currentPath){ return allowChange; }
+
+ allowChange = true;
+
+ for(i=0, li=routes.length; i<li; ++i){
+ routeObj = routes[i];
+ result = routeObj.route.exec(newPath);
+
+ if(result){
+ if(routeObj.parameterNames){
+ parameterNames = routeObj.parameterNames;
+ params = {};
+
+ for(j=0, lj=parameterNames.length; j<lj; ++j){
+ params[parameterNames[j]] = result[j+1];
+ }
+ }else{
+ params = result.slice(1);
+ }
+ allowChange = routeObj.fire(params, currentPath, newPath);
+ }
+ }
+
+ if(allowChange){
+ this._currentPath = newPath;
+ }
+
+ return allowChange;
+ },
+
+ _convertRouteToRegExp: function(route){
+ // Sub in based on IDs and globs
+ route = route.replace(this.idMatch, this.idReplacement);
+ route = route.replace(this.globMatch, this.globReplacement);
+ // Make sure it's an exact match
+ route = "^" + route + "$";
+
+ return new RegExp(route);
+ },
+
+ _getParameterNames: function(route){
+ var idMatch = this.idMatch,
+ globMatch = this.globMatch,
+ parameterNames = [], match;
+
+ idMatch.lastIndex = 0;
+
+ while((match = idMatch.exec(route)) !== null){
+ parameterNames.push(match[1]);
+ }
+ if((match = globMatch.exec(route)) !== null){
+ parameterNames.push(match[1]);
+ }
+
+ return parameterNames.length > 0 ? parameterNames : null;
+ },
+
+ _indexRoutes: function(){
+ var i, l, route, routeIndex, routes = this._routes;
+
+ // Start a new route index
+ routeIndex = this._routeIndex = {};
+
+ // Set it up again
+ for(i=0, l=routes.length; i<l; ++i){
+ route = routes[i];
+ routeIndex[route.route] = i;
+ }
+ },
+
+ _registerRoute: function(/*String|RegExp*/route, /*Function*/callback, /*Boolean?*/isBefore){
+ var index, exists, routeObj, callbackQueue, removed,
+ self = this, routes = this._routes,
+ routeIndex = this._routeIndex;
+
+ // Try to fetch the route if it already exists.
+ // This works thanks to stringifying of regex
+ index = this._routeIndex[route];
+ exists = typeof index !== "undefined";
+ if(exists){
+ routeObj = routes[index];
+ }
+
+ // If we didn't get one, make a default start point
+ if(!routeObj){
+ routeObj = {
+ route: route,
+ callbackQueue: [],
+ fire: fireRoute
+ };
+ }
+
+ callbackQueue = routeObj.callbackQueue;
+
+ if(typeof route == "string"){
+ routeObj.parameterNames = this._getParameterNames(route);
+ routeObj.route = this._convertRouteToRegExp(route);
+ }
+
+ if(isBefore){
+ callbackQueue.unshift(callback);
+ }else{
+ callbackQueue.push(callback);
+ }
+
+ if(!exists){
+ index = routes.length;
+ routeIndex[route] = index;
+ routes.push(routeObj);
+ }
+
+ // Useful in a moment to keep from re-removing routes
+ removed = false;
+
+ return { // Object
+ remove: function(){
+ var i, l;
+
+ if(removed){ return; }
+
+ for(i=0, l=callbackQueue.length; i<l; ++i){
+ if(callbackQueue[i] === callback){
+ callbackQueue.splice(i, 1);
+ }
+ }
+
+
+ if(callbackQueue.length === 0){
+ routes.splice(index, 1);
+ self._indexRoutes();
+ }
+
+ removed = true;
+ },
+ register: function(callback, isBefore){
+ return self.register(route, callback, isBefore);
+ }
+ };
+ }
+ });
+
+ return RouterBase;
+});