From ea03a1483d790c7d87e02736051aba172a6c82b9 Mon Sep 17 00:00:00 2001 From: Nate Abele Date: Fri, 6 Dec 2013 14:17:51 -0500 Subject: [PATCH] release 0.2.6 --- README.md | 2 +- bower.json | 2 +- component.json | 2 +- package.json | 4 +- release/angular-ui-router.js | 198 +++++--- release/angular-ui-router.min.js | 4 +- release/doc/$resolve.html | 46 +- release/doc/$templateFactory.html | 61 ++- release/doc/$urlMatcherFactory.html | 25 +- release/doc/UrlMatcher.html | 64 +-- release/doc/common.js.html | 222 ++++++++ release/doc/global.html | 698 +++++++++++++++++++++++++- release/doc/index.html | 7 +- release/doc/resolve.js.html | 265 ++++++++++ release/doc/scripts/linenumber.js | 17 + release/doc/styles/jsdoc-default.css | 11 +- release/doc/templateFactory.js.html | 137 +++++ release/doc/urlMatcherFactory.js.html | 306 +++++++++++ 18 files changed, 1915 insertions(+), 156 deletions(-) create mode 100644 release/doc/common.js.html create mode 100644 release/doc/resolve.js.html create mode 100644 release/doc/scripts/linenumber.js create mode 100644 release/doc/templateFactory.js.html create mode 100644 release/doc/urlMatcherFactory.js.html diff --git a/README.md b/README.md index ac9a095c5..38dbdc5d2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ #### The de-facto solution to flexible routing with nested views --- -**[Download 0.2.5](http://angular-ui.github.io/ui-router/release/angular-ui-router.js)** (or **[Minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)**) **|** +**[Download 0.2.6](http://angular-ui.github.io/ui-router/release/angular-ui-router.js)** (or **[Minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)**) **|** **[Learn](#resources) |** **[Discuss](https://groups.google.com/forum/#!categories/angular-ui/router) |** **[Get Help](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) |** diff --git a/bower.json b/bower.json index 5b885fb5f..f01f70d41 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-ui-router", - "version": "0.2.5", + "version": "0.2.6", "main": "./release/angular-ui-router.js", "dependencies": { "angular": ">= 1.1.5" diff --git a/component.json b/component.json index 1ecd5307d..bb0c6cd2a 100644 --- a/component.json +++ b/component.json @@ -1,6 +1,6 @@ { "name": "angular-ui-router", - "version": "0.2.5", + "version": "0.2.6", "description": "State-based routing for AngularJS", "keywords": [ "angular", diff --git a/package.json b/package.json index de69ed37a..25ccc6b19 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-ui-router", "description": "State-based routing for AngularJS", - "version": "0.2.5", + "version": "0.2.6", "homepage": "http://angular-ui.github.com/", "contributors": [ { @@ -52,7 +52,7 @@ "karma-chrome-launcher": "~0.1.0", "karma-html2js-preprocessor": "~0.1.0", "karma-jasmine": "~0.1.3", - "karma-requirejs": "~0.1.0", + "karma-requirejs": "~0.2.0", "karma-script-launcher": "~0.1.0", "karma-coffee-preprocessor": "~0.1.0", "karma": "~0.10.4", diff --git a/release/angular-ui-router.js b/release/angular-ui-router.js index 716a7e3bc..79827ec9a 100644 --- a/release/angular-ui-router.js +++ b/release/angular-ui-router.js @@ -1,6 +1,6 @@ /** * State-based routing for AngularJS - * @version v0.2.5 + * @version v0.2.6 * @link http://angular-ui.github.com/ * @license MIT License, http://www.opensource.org/licenses/MIT */ @@ -57,6 +57,24 @@ function ancestors(first, second) { return path; } +/** + * IE8-safe wrapper for `Object.keys()`. + * + * @param {Object} object A JavaScript object. + * @return {Array} Returns the keys of the object as an array. + */ +function keys(object) { + if (Object.keys) { + return Object.keys(object); + } + var result = []; + + angular.forEach(object, function(val, key) { + result.push(key); + }); + return result; +} + /** * IE8-safe wrapper for `Array.prototype.indexOf()`. * @@ -104,6 +122,61 @@ function inheritParams(currentParams, newParams, $current, $to) { return extend({}, inherited, newParams); } +/** + * Normalizes a set of values to string or `null`, filtering them by a list of keys. + * + * @param {Array} keys The list of keys to normalize/return. + * @param {Object} values An object hash of values to normalize. + * @return {Object} Returns an object hash of normalized string values. + */ +function normalize(keys, values) { + var normalized = {}; + + forEach(keys, function (name) { + var value = values[name]; + normalized[name] = (value != null) ? String(value) : null; + }); + return normalized; +} + +/** + * Performs a non-strict comparison of the subset of two objects, defined by a list of keys. + * + * @param {Object} a The first object. + * @param {Object} b The second object. + * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified, + * it defaults to the list of keys in `a`. + * @return {Boolean} Returns `true` if the keys match, otherwise `false`. + */ +function equalForKeys(a, b, keys) { + if (!keys) { + keys = []; + for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility + } + + for (var i=0; i>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function h(a,b,c,d){var e,h=f(c,d),i={},j=[];for(var k in h)if(h[k].params&&h[k].params.length){e=h[k].params;for(var l in e)g(j,e[l])>=0||(j.push(e[l]),i[e[l]]=a[e[l]])}return z({},i,b)}function i(a,b){var d=1,f=2,g={},h=[],i=g,j=z(a.when(g),{$$promises:g,$$values:g});this.study=function(g){function k(a,c){if(o[c]!==f){if(n.push(c),o[c]===d)throw n.splice(0,n.indexOf(c)),new Error("Cyclic dependency: "+n.join(" -> "));if(o[c]=d,v(a))m.push(c,[function(){return b.get(a)}],h);else{var e=b.annotate(a);y(e,function(a){a!==c&&g.hasOwnProperty(a)&&k(g[a],a)}),m.push(c,a,e)}n.pop(),o[c]=f}}function l(a){return w(a)&&a.then&&a.$$promises}if(!w(g))throw new Error("'invocables' must be an object");var m=[],n=[],o={};return y(g,k),g=n=o=null,function(d,f,g){function h(){--s||(u||e(r,f.$$values),p.$$values=r,p.$$promises=!0,o.resolve(r))}function k(a){p.$$failure=a,o.reject(a)}function n(c,e,f){function i(a){l.reject(a),k(a)}function j(){if(!t(p.$$failure))try{l.resolve(b.invoke(e,g,r)),l.promise.then(function(a){r[c]=a,h()},i)}catch(a){i(a)}}var l=a.defer(),m=0;y(f,function(a){q.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,q[a].then(function(b){r[a]=b,--m||j()},i))}),m||j(),q[c]=l.promise}if(l(d)&&g===c&&(g=f,f=d,d=null),d){if(!w(d))throw new Error("'locals' must be an object")}else d=i;if(f){if(!l(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=j;var o=a.defer(),p=o.promise,q=p.$$promises={},r=z({},d),s=1+m.length/3,u=!1;if(t(f.$$failure))return k(f.$$failure),p;f.$$values?(u=e(r,f.$$values),h()):(z(q,f.$$promises),f.then(h,k));for(var v=0,x=m.length;x>v;v+=3)d.hasOwnProperty(m[v])?h():n(m[v],m[v+1],m[v+2]);return p}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function j(a,b,c){this.fromConfig=function(a,b,c){return t(a.template)?this.fromString(a.template,b):t(a.templateUrl)?this.fromUrl(a.templateUrl,b):t(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return u(a)?a(b):a},this.fromUrl=function(c,d){return u(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function k(a){function b(b){if(!/^\w+(-+\w+)*$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(f[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");f[b]=!0,j.push(b)}function c(a){return a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&")}var d,e=/([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f={},g="^",h=0,i=this.segments=[],j=this.params=[];this.source=a;for(var k,l,m;(d=e.exec(a))&&(k=d[2]||d[3],l=d[4]||("*"==d[1]?".*":"[^/]*"),m=a.substring(h,d.index),!(m.indexOf("?")>=0));)g+=c(m)+"("+l+")",b(k),i.push(m),h=e.lastIndex;m=a.substring(h);var n=m.indexOf("?");if(n>=0){var o=this.sourceSearch=m.substring(n);m=m.substring(0,n),this.sourcePath=a.substring(0,h+n),y(o.substring(1).split(/[&?]/),b)}else this.sourcePath=a,this.sourceSearch="";g+=c(m)+"$",i.push(m),this.regexp=new RegExp(g),this.prefix=i[0]}function l(){this.compile=function(a){return new k(a)},this.isMatcher=function(a){return w(a)&&u(a.exec)&&u(a.format)&&u(a.concat)},this.$get=function(){return this}}function m(a){function b(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function c(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function d(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return t(d)?d:!0}var e=[],f=null;this.rule=function(a){if(!u(a))throw new Error("'rule' must be a function");return e.push(a),this},this.otherwise=function(a){if(v(a)){var b=a;a=function(){return b}}else if(!u(a))throw new Error("'rule' must be a function");return f=a,this},this.when=function(e,f){var g,h=v(f);if(v(e)&&(e=a.compile(e)),!h&&!u(f)&&!x(f))throw new Error("invalid 'handler' in when()");var i={matcher:function(b,c){return h&&(g=a.compile(c),c=["$match",function(a){return g.format(a)}]),z(function(a,e){return d(a,c,b.exec(e.path(),e.search()))},{prefix:v(b.prefix)?b.prefix:""})},regex:function(a,e){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(g=e,e=["$match",function(a){return c(g,a)}]),z(function(b,c){return d(b,e,a.exec(c.path()))},{prefix:b(a)})}},j={matcher:a.isMatcher(e),regex:e instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](e,f));throw new Error("invalid 'what' in when()")},this.$get=["$location","$rootScope","$injector",function(a,b,c){function d(b){function d(b){var d=b(c,a);return d?(v(d)&&a.replace().url(d),!0):!1}if(!b||!b.defaultPrevented){var g,h=e.length;for(g=0;h>g;g++)if(d(e[g]))return;f&&d(f)}}return b.$on("$locationChangeSuccess",d),{sync:function(){d()}}}]}function n(a,e,f){function g(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function i(a,b){var d=v(a),e=d?a:a.name,f=g(e);if(f){if(!b)throw new Error("No reference point given for path '"+e+"'");for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=C[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function j(a,b){D[a]||(D[a]=[]),D[a].push(b)}function k(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!v(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(C.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):v(b.parent)?b.parent:"";if(e&&!C[e])return j(e,b.self);for(var f in E)u(E[f])&&(b[f]=E[f](b,E.$delegates[f]));if(C[c]=b,!b["abstract"]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){B.$current.navigable==b&&p(a,c)||B.transitionTo(b,a,!1)}]),D[c])for(var g=0;g=H;d--)g=u[d],g.self.onExit&&j.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=H;d").html(a).contents();return r.enter(d,c),d}},"false":{remove:function(a){a.html("")},restore:function(a,b){b.append(a)},populate:function(a,b){return b.html(a),b.contents()}}}[a.toString()]};h.append(s);var v=h.parent().inheritedData("$uiView");p.indexOf("@")<0&&(p=p+"@"+(v?v.state.name:""));var w={name:p,state:null};h.data("$uiView",w);var x=function(){if(!i){i=!0;try{m(!0)}catch(a){throw i=!1,a}i=!1}};e.$on("$stateChangeSuccess",x),e.$on("$viewContentLoading",x),m(!1)}}};return j}function q(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function r(a){return{restrict:"A",link:function(b,c,d){var e=q(d.uiSref),f=null,g=a.$current,h="FORM"===c[0].nodeName,i=h?"action":"href",j=!0,k=c.parent().inheritedData("$uiView");k&&k.state&&k.state.name&&(g=k.state);var l=function(b){if(b&&(f=b),j){var d=a.href(e.state,f,{relative:g});return d?(c[0][i]=d,void 0):(j=!1,!1)}};e.paramExpr&&(b.$watch(e.paramExpr,function(a){a!==f&&l(a)},!0),f=b.$eval(e.paramExpr)),l(),h||c.bind("click",function(c){var d=c.which||c.button;0!==d&&1!=d||c.ctrlKey||c.metaKey||c.shiftKey||(b.$evalAsync(function(){a.go(e.state,f,{relative:g})}),c.preventDefault())})}}}function s(a,b){function e(a){this.locals=a.locals.globals,this.params=this.locals.$stateParams}function f(){this.locals=null,this.params=null}function g(c,g){if(null!=g.redirectTo){var h,j=g.redirectTo;if(v(j))h=j;else{if(!u(j))throw new Error("Invalid 'redirectTo' in when()");h=function(a,b){return j(a,b.path(),b.search())}}b.when(c,h)}else a.state(d(g,{parent:null,name:"route:"+encodeURIComponent(c),url:c,onEnter:e,onExit:f}));return i.push(g),this}function h(a,b,d){function e(a){return""!==a.name?a:c}var f={routes:i,params:d,current:c};return b.$on("$stateChangeStart",function(a,c,d,f){b.$broadcast("$routeChangeStart",e(c),e(f))}),b.$on("$stateChangeSuccess",function(a,c,d,g){f.current=e(c),b.$broadcast("$routeChangeSuccess",e(c),e(g)),A(d,f.params)}),b.$on("$stateChangeError",function(a,c,d,f,g,h){b.$broadcast("$routeChangeError",e(c),e(f),h)}),f}var i=[];e.$inject=["$$state"],this.when=g,this.$get=h,h.$inject=["$state","$rootScope","$routeParams"]}var t=b.isDefined,u=b.isFunction,v=b.isString,w=b.isObject,x=b.isArray,y=b.forEach,z=b.extend,A=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),i.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",i),j.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",j),k.prototype.concat=function(a){return new k(this.sourcePath+a+this.sourceSearch)},k.prototype.toString=function(){return this.source},k.prototype.exec=function(a,b){var c=this.regexp.exec(a);if(!c)return null;var d,e=this.params,f=e.length,g=this.segments.length-1,h={};if(g!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(d=0;g>d;d++)h[e[d]]=c[d+1];for(;f>d;d++)h[e[d]]=b[e[d]];return h},k.prototype.parameters=function(){return this.params},k.prototype.format=function(a){var b=this.segments,c=this.params;if(!a)return b.join("");var d,e,f,g=b.length-1,h=c.length,i=b[0];for(d=0;g>d;d++)f=a[c[d]],null!=f&&(i+=encodeURIComponent(f)),i+=b[d+1];for(;h>d;d++)f=a[c[d]],null!=f&&(i+=(e?"&":"?")+c[d]+"="+encodeURIComponent(f),e=!0);return i},b.module("ui.router.util").provider("$urlMatcherFactory",l),m.$inject=["$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",m),n.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider","$locationProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",n),o.$inject=[],b.module("ui.router.state").provider("$view",o),p.$inject=["$state","$compile","$controller","$injector","$anchorScroll"],b.module("ui.router.state").directive("uiView",p),r.$inject=["$state"],b.module("ui.router.state").directive("uiSref",r),s.$inject=["$stateProvider","$urlRouterProvider"],b.module("ui.router.compat").provider("$route",s).directive("ngView",p)}(window,window.angular); \ No newline at end of file +"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return E(new(E(function(){},{prototype:a})),b)}function e(a){return D(arguments,function(b){b!==a&&D(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path)if(""!==a.path[d]){if(!b.path[d])break;c.push(a.path[d])}return c}function g(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function h(a,b,c,d){var e,h=f(c,d),i={},j=[];for(var k in h)if(h[k].params&&h[k].params.length){e=h[k].params;for(var l in e)g(j,e[l])>=0||(j.push(e[l]),i[e[l]]=a[e[l]])}return E({},i,b)}function i(a,b){var c={};return D(a,function(a){var d=b[a];c[a]=null!=d?String(d):null}),c}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(o[c]=d,A(a))m.push(c,[function(){return b.get(a)}],h);else{var e=b.annotate(a);D(e,function(a){a!==c&&g.hasOwnProperty(a)&&k(g[a],a)}),m.push(c,a,e)}n.pop(),o[c]=f}}function l(a){return B(a)&&a.then&&a.$$promises}if(!B(g))throw new Error("'invocables' must be an object");var m=[],n=[],o={};return D(g,k),g=n=o=null,function(d,f,g){function h(){--s||(t||e(r,f.$$values),p.$$values=r,p.$$promises=!0,o.resolve(r))}function k(a){p.$$failure=a,o.reject(a)}function n(c,e,f){function i(a){l.reject(a),k(a)}function j(){if(!y(p.$$failure))try{l.resolve(b.invoke(e,g,r)),l.promise.then(function(a){r[c]=a,h()},i)}catch(a){i(a)}}var l=a.defer(),m=0;D(f,function(a){q.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,q[a].then(function(b){r[a]=b,--m||j()},i))}),m||j(),q[c]=l.promise}if(l(d)&&g===c&&(g=f,f=d,d=null),d){if(!B(d))throw new Error("'locals' must be an object")}else d=i;if(f){if(!l(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=j;var o=a.defer(),p=o.promise,q=p.$$promises={},r=E({},d),s=1+m.length/3,t=!1;if(y(f.$$failure))return k(f.$$failure),p;f.$$values?(t=e(r,f.$$values),h()):(E(q,f.$$promises),f.then(h,k));for(var u=0,v=m.length;v>u;u+=3)d.hasOwnProperty(m[u])?h():n(m[u],m[u+1],m[u+2]);return p}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function m(a,b,c){this.fromConfig=function(a,b,c){return y(a.template)?this.fromString(a.template,b):y(a.templateUrl)?this.fromUrl(a.templateUrl,b):y(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return z(a)?a(b):a},this.fromUrl=function(c,d){return z(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function n(a){function b(b){if(!/^\w+(-+\w+)*$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(f[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");f[b]=!0,j.push(b)}function c(a){return a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&")}var d,e=/([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f={},g="^",h=0,i=this.segments=[],j=this.params=[];this.source=a;for(var k,l,m;(d=e.exec(a))&&(k=d[2]||d[3],l=d[4]||("*"==d[1]?".*":"[^/]*"),m=a.substring(h,d.index),!(m.indexOf("?")>=0));)g+=c(m)+"("+l+")",b(k),i.push(m),h=e.lastIndex;m=a.substring(h);var n=m.indexOf("?");if(n>=0){var o=this.sourceSearch=m.substring(n);m=m.substring(0,n),this.sourcePath=a.substring(0,h+n),D(o.substring(1).split(/[&?]/),b)}else this.sourcePath=a,this.sourceSearch="";g+=c(m)+"$",i.push(m),this.regexp=new RegExp(g),this.prefix=i[0]}function o(){this.compile=function(a){return new n(a)},this.isMatcher=function(a){return B(a)&&z(a.exec)&&z(a.format)&&z(a.concat)},this.$get=function(){return this}}function p(a){function b(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function c(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function d(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return y(d)?d:!0}var e=[],f=null;this.rule=function(a){if(!z(a))throw new Error("'rule' must be a function");return e.push(a),this},this.otherwise=function(a){if(A(a)){var b=a;a=function(){return b}}else if(!z(a))throw new Error("'rule' must be a function");return f=a,this},this.when=function(e,f){var g,h=A(f);if(A(e)&&(e=a.compile(e)),!h&&!z(f)&&!C(f))throw new Error("invalid 'handler' in when()");var i={matcher:function(b,c){return h&&(g=a.compile(c),c=["$match",function(a){return g.format(a)}]),E(function(a,e){return d(a,c,b.exec(e.path(),e.search()))},{prefix:A(b.prefix)?b.prefix:""})},regex:function(a,e){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(g=e,e=["$match",function(a){return c(g,a)}]),E(function(b,c){return d(b,e,a.exec(c.path()))},{prefix:b(a)})}},j={matcher:a.isMatcher(e),regex:e instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](e,f));throw new Error("invalid 'what' in when()")},this.$get=["$location","$rootScope","$injector",function(a,b,c){function d(b){function d(b){var d=b(c,a);return d?(A(d)&&a.replace().url(d),!0):!1}if(!b||!b.defaultPrevented){var g,h=e.length;for(g=0;h>g;g++)if(d(e[g]))return;f&&d(f)}}return b.$on("$locationChangeSuccess",d),{sync:function(){d()}}}]}function q(a,e,f){function g(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){var d=A(a),e=d?a:a.name,f=g(e);if(f){if(!b)throw new Error("No reference point given for path '"+e+"'");for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=u[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function m(a,b){v[a]||(v[a]=[]),v[a].push(b)}function n(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!A(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(u.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):A(b.parent)?b.parent:"";if(e&&!u[e])return m(e,b.self);for(var f in x)z(x[f])&&(b[f]=x[f](b,x.$delegates[f]));if(u[c]=b,!b[w]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){t.$current.navigable==b&&j(a,c)||t.transitionTo(b,a,{location:!1})}]),v[c])for(var g=0;g=I;d--)g=u[d],g.self.onExit&&m.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=I;d").html(a).contents();return r.enter(d,c),d}},"false":{remove:function(a){a.html("")},restore:function(a,b){b.append(a)},populate:function(a,b){return b.html(a),b.contents()}}}[a.toString()]};j.append(s);var u=j.parent().inheritedData("$uiView");p.indexOf("@")<0&&(p=p+"@"+(u?u.state.name:""));var v={name:p,state:null};j.data("$uiView",v);var w=function(){if(!h){h=!0;try{m(!0)}catch(a){throw h=!1,a}h=!1}};e.$on("$stateChangeSuccess",w),e.$on("$viewContentLoading",w),m(!1)}}};return i}function t(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function u(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function v(a,b){return{restrict:"A",require:"?^uiSrefActive",link:function(c,d,e,f){var g=t(e.uiSref),h=null,i=u(d)||a.$current,j="FORM"===d[0].nodeName,k=j?"action":"href",l=!0,m=function(b){if(b&&(h=b),l){var c=a.href(g.state,h,{relative:i});if(!c)return l=!1,!1;d[0][k]=c,f&&f.$$setStateInfo(g.state,h)}};g.paramExpr&&(c.$watch(g.paramExpr,function(a){a!==h&&m(a)},!0),h=c.$eval(g.paramExpr)),m(),j||d.bind("click",function(d){var e=d.which||d.button;0!==e&&1!=e||d.ctrlKey||d.metaKey||d.shiftKey||(b(function(){c.$apply(function(){a.go(g.state,h,{relative:i})})}),d.preventDefault())})}}}function w(a,b,c){return{restrict:"A",controller:function(d,e,f){function g(){a.$current.self===i&&h()?e.addClass(l):e.removeClass(l)}function h(){return!k||j(k,b)}var i,k,l;l=c(f.uiSrefActive||"",!1)(d),this.$$setStateInfo=function(b,c){i=a.get(b,u(e)),k=c,g()},d.$on("$stateChangeSuccess",g)}}}function x(a,b){function e(a){this.locals=a.locals.globals,this.params=this.locals.$stateParams}function f(){this.locals=null,this.params=null}function g(c,g){if(null!=g.redirectTo){var h,j=g.redirectTo;if(A(j))h=j;else{if(!z(j))throw new Error("Invalid 'redirectTo' in when()");h=function(a,b){return j(a,b.path(),b.search())}}b.when(c,h)}else a.state(d(g,{parent:null,name:"route:"+encodeURIComponent(c),url:c,onEnter:e,onExit:f}));return i.push(g),this}function h(a,b,d){function e(a){return""!==a.name?a:c}var f={routes:i,params:d,current:c};return b.$on("$stateChangeStart",function(a,c,d,f){b.$broadcast("$routeChangeStart",e(c),e(f))}),b.$on("$stateChangeSuccess",function(a,c,d,g){f.current=e(c),b.$broadcast("$routeChangeSuccess",e(c),e(g)),F(d,f.params)}),b.$on("$stateChangeError",function(a,c,d,f,g,h){b.$broadcast("$routeChangeError",e(c),e(f),h)}),f}var i=[];e.$inject=["$$state"],this.when=g,this.$get=h,h.$inject=["$state","$rootScope","$routeParams"]}var y=b.isDefined,z=b.isFunction,A=b.isString,B=b.isObject,C=b.isArray,D=b.forEach,E=b.extend,F=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),l.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",l),m.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",m),n.prototype.concat=function(a){return new n(this.sourcePath+a+this.sourceSearch)},n.prototype.toString=function(){return this.source},n.prototype.exec=function(a,b){var c=this.regexp.exec(a);if(!c)return null;var d,e=this.params,f=e.length,g=this.segments.length-1,h={};if(g!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(d=0;g>d;d++)h[e[d]]=c[d+1];for(;f>d;d++)h[e[d]]=b[e[d]];return h},n.prototype.parameters=function(){return this.params},n.prototype.format=function(a){var b=this.segments,c=this.params;if(!a)return b.join("");var d,e,f,g=b.length-1,h=c.length,i=b[0];for(d=0;g>d;d++)f=a[c[d]],null!=f&&(i+=encodeURIComponent(f)),i+=b[d+1];for(;h>d;d++)f=a[c[d]],null!=f&&(i+=(e?"&":"?")+c[d]+"="+encodeURIComponent(f),e=!0);return i},b.module("ui.router.util").provider("$urlMatcherFactory",o),p.$inject=["$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",p),q.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider","$locationProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",q),r.$inject=[],b.module("ui.router.state").provider("$view",r),s.$inject=["$state","$compile","$controller","$injector","$anchorScroll"],b.module("ui.router.state").directive("uiView",s),v.$inject=["$state","$timeout"],w.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",v).directive("uiSrefActive",w),x.$inject=["$stateProvider","$urlRouterProvider"],b.module("ui.router.compat").provider("$route",x).directive("ngView",s)}(window,window.angular); \ No newline at end of file diff --git a/release/doc/$resolve.html b/release/doc/$resolve.html index d5d9f80ba..c29ce9bc2 100644 --- a/release/doc/$resolve.html +++ b/release/doc/$resolve.html @@ -64,7 +64,7 @@

Source:
@@ -118,40 +118,32 @@

resolve$q promise. If a promise is returned it will be resolved and the resulting value will be used instead. Dependencies of invocables are resolved (in this order of precedence)

-
  • from the specified locals
  • from another invocable that is part of this $resolve call
  • from an invocable that is inherited from a parent call to $resolve (or recursively from any ancestor $resolve of that parent).
-

The return value of $resolve is a promise for an object that contains (in this order of precedence)

-
  • any locals (if specified)
  • the resolved return values of all injectables
  • any values inherited from a parent call to $resolve (if specified)
-

The promise will resolve after the parent promise (if any) and all promises returned by injectables have been resolved. If any invocable (or $injector.invoke) throws an exception, or if a promise returned by an invocable is rejected, the $resolve promise is immediately rejected with the same error. A rejection of a parent promise (if specified) will likewise be propagated immediately. Once the $resolve promise has been rejected, no further invocables will be called.

-

Cyclic dependencies between invocables are not permitted and will caues $resolve to throw an error. As a special case, an injectable can depend on a parameter with the same name as the injectable, which will be fulfilled from the parent injectable of the same name. This allows inherited values to be decorated. Note that in this case any other injectable in the same $resolve with the same dependency would see the decorated value, not the inherited value.

-

Note that missing dependencies -- unlike cyclic dependencies -- will cause an (asynchronous) rejection of the $resolve promise rather than a (synchronous) exception.

-

Invocables are invoked eagerly as soon as all dependencies are available. This is true even for dependencies inherited from a parent call to $resolve.

-

As a special case, an invocable can be a string, in which case it is taken to be a service name to be passed to $injector.get(). This is supported primarily for backwards-compatibility with the resolve property of $routeProvider routes.

@@ -196,10 +188,7 @@
Parameters:
-Object.<string, Function -| - -string> +Object.<string, (function()|string)> @@ -210,6 +199,8 @@
Parameters:
+ + @@ -241,6 +232,8 @@
Parameters:
+ + @@ -272,6 +265,8 @@
Parameters:
+ + @@ -303,6 +298,8 @@
Parameters:
+ + @@ -339,7 +336,7 @@
Parameters:
Source:
@@ -352,6 +349,10 @@
Parameters:
+ + + + @@ -386,7 +387,7 @@
Returns:
-

study(invocables) → {Function}

+

study(invocables) → {function}

@@ -480,7 +481,7 @@
Parameters:
Source:
@@ -493,6 +494,10 @@
Parameters:
+ + + + @@ -508,7 +513,7 @@
Returns:
-Function +function
@@ -535,15 +540,16 @@
Returns:

- Documentation generated by JSDoc 3.1.1 on Wed Dec 04 2013 21:16:33 GMT-0500 (EST) + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST)
+ - + \ No newline at end of file diff --git a/release/doc/$templateFactory.html b/release/doc/$templateFactory.html index 1e5b5ff0f..87f0e3804 100644 --- a/release/doc/$templateFactory.html +++ b/release/doc/$templateFactory.html @@ -80,7 +80,7 @@

new $
Source:
@@ -93,6 +93,10 @@

new $ + + + + @@ -193,6 +197,8 @@

Parameters:
+ + @@ -235,7 +241,7 @@
Properties
string | -Function +function @@ -262,7 +268,7 @@
Properties
string | -Function +function @@ -286,7 +292,7 @@
Properties
-Function +function @@ -327,6 +333,8 @@
Properties
+ + @@ -358,6 +366,8 @@
Properties
+ + @@ -395,7 +405,7 @@
Properties
Source:
@@ -408,6 +418,10 @@
Properties
+ + + + @@ -496,7 +510,7 @@
Parameters:
string | -Function +function @@ -561,7 +575,7 @@
Parameters:
Source:
@@ -574,6 +588,10 @@
Parameters:
+ + + + @@ -661,7 +679,7 @@
Parameters:
string | -Function +function @@ -725,7 +743,7 @@
Parameters:
Source:
@@ -738,6 +756,10 @@
Parameters:
+ + + + @@ -824,7 +846,7 @@
Parameters:
-Function +function @@ -835,6 +857,8 @@
Parameters:
+ + @@ -864,6 +888,8 @@
Parameters:
+ + @@ -895,6 +921,8 @@
Parameters:
+ + @@ -931,7 +959,7 @@
Parameters:
Source:
@@ -944,6 +972,10 @@
Parameters:
+ + + + @@ -993,15 +1025,16 @@
Returns:

- Documentation generated by JSDoc 3.1.1 on Wed Dec 04 2013 21:16:33 GMT-0500 (EST) + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST)
+ - + \ No newline at end of file diff --git a/release/doc/$urlMatcherFactory.html b/release/doc/$urlMatcherFactory.html index e508010a8..c5f087724 100644 --- a/release/doc/$urlMatcherFactory.html +++ b/release/doc/$urlMatcherFactory.html @@ -81,7 +81,7 @@

new
Source:
@@ -94,6 +94,10 @@

new + + + + @@ -212,7 +216,7 @@

Parameters:
Source:
@@ -225,6 +229,10 @@
Parameters:
+ + + + @@ -347,7 +355,7 @@
Parameters:
Source:
@@ -360,6 +368,10 @@
Parameters:
+ + + + @@ -402,15 +414,16 @@
Returns:

- Documentation generated by JSDoc 3.1.1 on Wed Dec 04 2013 21:16:33 GMT-0500 (EST) + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST)
+ - + \ No newline at end of file diff --git a/release/doc/UrlMatcher.html b/release/doc/UrlMatcher.html index c4aa2b9c9..5f787425c 100644 --- a/release/doc/UrlMatcher.html +++ b/release/doc/UrlMatcher.html @@ -52,10 +52,8 @@

new UrlMatc of search parameters. Multiple search parameter names are separated by '&'. Search parameters do not influence whether or not a URL is matched, but their values are passed through into the matched parameters returned by exec.

-

Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace syntax, which optionally allows a regular expression for the parameter to be specified:

-
  • ':' name - colon placeholder
  • '*' name - catch-all placeholder
  • @@ -63,15 +61,12 @@

    new UrlMatc
  • '{' name ':' regexp '}' - curly placeholder with regexp. Should the regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.
-

Parameter names may contain only word characters (latin letters, digits, and underscore) and must be unique within the pattern (across both path and search parameters). For colon placeholders or curly placeholders without an explicit regexp, a path parameter matches any number of characters other than '/'. For catch-all placeholders the path parameter matches any number of characters.

-

Examples

-
  • '/hello/' - Matches only if the path is exactly '/hello/'. There is no special treatment for trailing slashes, and patterns have to match the entire path, not just a prefix.
  • @@ -218,7 +213,7 @@
    Properties:
    Source:
    @@ -231,6 +226,10 @@
    Properties:
    + + + + @@ -272,14 +271,10 @@

    concat -

    Example

    -

    The following two matchers are equivalent:

    - -
    new UrlMatcher('/user/{id}?q').concat('/details?date');
    -new UrlMatcher('/user/{id}/details?q&date');
    -
    +
    new UrlMatcher('/user/{id}?q').concat('/details?date');
    +new UrlMatcher('/user/{id}/details?q&date');
    @@ -360,7 +355,7 @@
    Parameters:
    Source:
    @@ -373,6 +368,10 @@
    Parameters:
    + + + + @@ -419,12 +418,9 @@

    exec
    new UrlMatcher('/user/{id}?q&r').exec('/user/bob', { x:'1', q:'hello' });
    -// returns { id:'bob', q:'hello', r:null }
    -
    +
    new UrlMatcher('/user/{id}?q&r').exec('/user/bob', { x:'1', q:'hello' });
    +// returns { id:'bob', q:'hello', r:null }
    @@ -528,7 +524,7 @@
    Parameters:
    Source:
    @@ -541,6 +537,10 @@
    Parameters:
    + + + + @@ -585,12 +585,9 @@

    formatCreates a URL that matches this pattern by substituting the specified values for the path and search parameters. Null values for path parameters are treated as empty strings.

    -

    Example

    - -
    new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
    -// returns '/user/bob?q=yes'
    -
    +
    new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
    +// returns '/user/bob?q=yes'
    @@ -671,7 +668,7 @@
    Parameters:
    Source:
    @@ -684,6 +681,10 @@
    Parameters:
    + + + + @@ -758,7 +759,7 @@

    parameters<
    Source:
    @@ -771,6 +772,10 @@

    parameters< + + + + @@ -818,15 +823,16 @@

    Returns:

    - Documentation generated by JSDoc 3.1.1 on Wed Dec 04 2013 21:16:33 GMT-0500 (EST) + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST)
    + - + \ No newline at end of file diff --git a/release/doc/common.js.html b/release/doc/common.js.html new file mode 100644 index 000000000..f4b520d6e --- /dev/null +++ b/release/doc/common.js.html @@ -0,0 +1,222 @@ + + + + + JSDoc: Source: common.js + + + + + + + + + + +
    + +

    Source: common.js

    + + + + + +
    +
    +
    /*jshint globalstrict:true*/
    +/*global angular:false*/
    +'use strict';
    +
    +var isDefined = angular.isDefined,
    +    isFunction = angular.isFunction,
    +    isString = angular.isString,
    +    isObject = angular.isObject,
    +    isArray = angular.isArray,
    +    forEach = angular.forEach,
    +    extend = angular.extend,
    +    copy = angular.copy;
    +
    +function inherit(parent, extra) {
    +  return extend(new (extend(function() {}, { prototype: parent }))(), extra);
    +}
    +
    +function merge(dst) {
    +  forEach(arguments, function(obj) {
    +    if (obj !== dst) {
    +      forEach(obj, function(value, key) {
    +        if (!dst.hasOwnProperty(key)) dst[key] = value;
    +      });
    +    }
    +  });
    +  return dst;
    +}
    +
    +/**
    + * Finds the common ancestor path between two states.
    + *
    + * @param {Object} first The first state.
    + * @param {Object} second The second state.
    + * @return {Array} Returns an array of state names in descending order, not including the root.
    + */
    +function ancestors(first, second) {
    +  var path = [];
    +
    +  for (var n in first.path) {
    +    if (first.path[n] === "") continue;
    +    if (!second.path[n]) break;
    +    path.push(first.path[n]);
    +  }
    +  return path;
    +}
    +
    +/**
    + * IE8-safe wrapper for `Object.keys()`.
    + *
    + * @param {Object} object A JavaScript object.
    + * @return {Array} Returns the keys of the object as an array.
    + */
    +function keys(object) {
    +  if (Object.keys) {
    +    return Object.keys(object);
    +  }
    +  var result = [];
    +
    +  angular.forEach(object, function(val, key) {
    +    result.push(key);
    +  });
    +  return result;
    +}
    +
    +/**
    + * IE8-safe wrapper for `Array.prototype.indexOf()`.
    + *
    + * @param {Array} array A JavaScript array.
    + * @param {*} value A value to search the array for.
    + * @return {Number} Returns the array index value of `value`, or `-1` if not present.
    + */
    +function arraySearch(array, value) {
    +  if (Array.prototype.indexOf) {
    +    return array.indexOf(value, Number(arguments[2]) || 0);
    +  }
    +  var len = array.length >>> 0, from = Number(arguments[2]) || 0;
    +  from = (from < 0) ? Math.ceil(from) : Math.floor(from);
    +
    +  if (from < 0) from += len;
    +
    +  for (; from < len; from++) {
    +    if (from in array && array[from] === value) return from;
    +  }
    +  return -1;
    +}
    +
    +/**
    + * Merges a set of parameters with all parameters inherited between the common parents of the
    + * current state and a given destination state.
    + *
    + * @param {Object} currentParams The value of the current state parameters ($stateParams).
    + * @param {Object} newParams The set of parameters which will be composited with inherited params.
    + * @param {Object} $current Internal definition of object representing the current state.
    + * @param {Object} $to Internal definition of object representing state to transition to.
    + */
    +function inheritParams(currentParams, newParams, $current, $to) {
    +  var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];
    +
    +  for (var i in parents) {
    +    if (!parents[i].params || !parents[i].params.length) continue;
    +    parentParams = parents[i].params;
    +
    +    for (var j in parentParams) {
    +      if (arraySearch(inheritList, parentParams[j]) >= 0) continue;
    +      inheritList.push(parentParams[j]);
    +      inherited[parentParams[j]] = currentParams[parentParams[j]];
    +    }
    +  }
    +  return extend({}, inherited, newParams);
    +}
    +
    +/**
    + * Normalizes a set of values to string or `null`, filtering them by a list of keys.
    + *
    + * @param {Array} keys The list of keys to normalize/return.
    + * @param {Object} values An object hash of values to normalize.
    + * @return {Object} Returns an object hash of normalized string values.
    + */
    +function normalize(keys, values) {
    +  var normalized = {};
    +
    +  forEach(keys, function (name) {
    +    var value = values[name];
    +    normalized[name] = (value != null) ? String(value) : null;
    +  });
    +  return normalized;
    +}
    +
    +/**
    + * Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
    + *
    + * @param {Object} a The first object.
    + * @param {Object} b The second object.
    + * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
    + *                     it defaults to the list of keys in `a`.
    + * @return {Boolean} Returns `true` if the keys match, otherwise `false`.
    + */
    +function equalForKeys(a, b, keys) {
    +  if (!keys) {
    +    keys = [];
    +    for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
    +  }
    +
    +  for (var i=0; i<keys.length; i++) {
    +    var k = keys[i];
    +    if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
    +  }
    +  return true;
    +}
    +
    +/**
    + * Returns the subset of an object, based on a list of keys.
    + *
    + * @param {Array} keys
    + * @param {Object} values
    + * @return {Boolean} Returns a subset of `values`.
    + */
    +function filterByKeys(keys, values) {
    +  var filtered = {};
    +
    +  forEach(keys, function (name) {
    +    filtered[name] = values[name];
    +  });
    +  return filtered;
    +}
    +
    +angular.module('ui.router.util', ['ng']);
    +angular.module('ui.router.router', ['ui.router.util']);
    +angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
    +angular.module('ui.router', ['ui.router.state']);
    +angular.module('ui.router.compat', ['ui.router']);
    +
    +
    +
    +
    + + + + +
    + + + +
    + +
    + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST) +
    + + + + + diff --git a/release/doc/global.html b/release/doc/global.html index 25f7a7cea..6a1415684 100644 --- a/release/doc/global.html +++ b/release/doc/global.html @@ -203,7 +203,7 @@
    Parameters:
    Source:
    @@ -216,6 +216,10 @@
    Parameters:
    + + + + @@ -361,7 +365,7 @@
    Parameters:
    Source:
    @@ -374,6 +378,10 @@
    Parameters:
    + + + + @@ -407,7 +415,7 @@
    Returns:
    -

    inheritParams(currentParams, newParams, $current, $to)

    +

    equalForKeys(a, b, keys) → {Boolean}

    @@ -415,8 +423,7 @@

    inheritP
    -

    Merges a set of parameters with all parameters inherited between the common parents of the -current state and a given destination state.

    +

    Performs a non-strict comparison of the subset of two objects, defined by a list of keys.

    @@ -450,7 +457,7 @@

    Parameters:
    - currentParams + a @@ -466,14 +473,14 @@
    Parameters:
    -

    The value of the current state parameters ($stateParams).

    +

    The first object.

    - newParams + b @@ -489,20 +496,20 @@
    Parameters:
    -

    The set of parameters which will be composited with inherited params.

    +

    The second object.

    - $current + keys -Object +Array @@ -512,14 +519,154 @@
    Parameters:
    -

    Internal definition of object representing the current state.

    +

    The list of keys within each object to compare. If the list is empty or not specified, + it defaults to the list of keys in a.

    + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    Source:
    +
    + + + + + + + +
    + + + + + + + + + + + +
    Returns:
    + + +
    +

    Returns true if the keys match, otherwise false.

    +
    + + + +
    +
    + Type +
    +
    + +Boolean + + +
    +
    + + + + + + + + +
    +

    filterByKeys(keys, values) → {Boolean}

    + + +
    +
    + + +
    +

    Returns the subset of an object, based on a list of keys.

    +
    + + + + + + + +
    Parameters:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + @@ -566,7 +713,7 @@
    Parameters:
    Source:
    @@ -579,10 +726,524 @@
    Parameters:
    + + + + + + + + +
    Returns:
    + + +
    +

    Returns a subset of values.

    +
    + + + +
    +
    + Type +
    +
    + +Boolean + + +
    +
    + + + + + + + + +
    +

    inheritParams(currentParams, newParams, $current, $to)

    + + +
    +
    + + +
    +

    Merges a set of parameters with all parameters inherited between the common parents of the +current state and a given destination state.

    +
    + + + +
    Parameters:
    + + +
    NameTypeDescription
    keys + + +Array + + + +
    $tovalues @@ -535,7 +682,7 @@
    Parameters:
    -

    Internal definition of object representing state to transition to.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    currentParams + + +Object + + + +

    The value of the current state parameters ($stateParams).

    newParams + + +Object + + + +

    The set of parameters which will be composited with inherited params.

    $current + + +Object + + + +

    Internal definition of object representing the current state.

    $to + + +Object + + + +

    Internal definition of object representing state to transition to.

    + + + +
    + + + + + + + + + + + + + + + + + + + +
    Source:
    +
    + + + + + + + +
    + + + + + + + + + + + + + +
    + + + +
    +

    keys(object) → {Array}

    + + +
    +
    + + +
    +

    IE8-safe wrapper for Object.keys().

    +
    + + + + + + + +
    Parameters:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    object + + +Object + + + +

    A JavaScript object.

    + + + +
    + + + + + + + + + + + + + + + + + + + +
    Source:
    +
    + + + + + + + +
    + + + + + + + + + + + +
    Returns:
    + + +
    +

    Returns the keys of the object as an array.

    +
    + + + +
    +
    + Type +
    +
    + +Array + + +
    +
    + + + + +
    + + + +
    +

    normalize(keys, values) → {Object}

    + + +
    +
    + + +
    +

    Normalizes a set of values to string or null, filtering them by a list of keys.

    +
    + + + + + + + +
    Parameters:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    keys + + +Array + + + +

    The list of keys to normalize/return.

    values + + +Object + + + +

    An object hash of values to normalize.

    + + + +
    + + + + + + + + + + + + + + + + + + + +
    Source:
    +
    + + + + + + + +
    + + + + + + + + + + + +
    Returns:
    + + +
    +

    Returns an object hash of normalized string values.

    +
    + + + +
    +
    + Type +
    +
    + +Object + + +
    +
    + +
    @@ -603,15 +1264,16 @@
    Parameters:

    - Documentation generated by JSDoc 3.1.1 on Wed Dec 04 2013 21:16:33 GMT-0500 (EST) + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST)
    + - + \ No newline at end of file diff --git a/release/doc/index.html b/release/doc/index.html index 18b459358..30205b49d 100644 --- a/release/doc/index.html +++ b/release/doc/index.html @@ -48,15 +48,16 @@


    - Documentation generated by JSDoc 3.1.1 on Wed Dec 04 2013 21:16:33 GMT-0500 (EST) + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST)
    + - + \ No newline at end of file diff --git a/release/doc/resolve.js.html b/release/doc/resolve.js.html new file mode 100644 index 000000000..30817bbb5 --- /dev/null +++ b/release/doc/resolve.js.html @@ -0,0 +1,265 @@ + + + + + JSDoc: Source: resolve.js + + + + + + + + + + +
    + +

    Source: resolve.js

    + + + + + +
    +
    +
    /**
    + * Service (`ui-util`). Manages resolution of (acyclic) graphs of promises.
    + * @module $resolve
    + * @requires $q
    + * @requires $injector
    + */
    +$Resolve.$inject = ['$q', '$injector'];
    +function $Resolve(  $q,    $injector) {
    +  
    +  var VISIT_IN_PROGRESS = 1,
    +      VISIT_DONE = 2,
    +      NOTHING = {},
    +      NO_DEPENDENCIES = [],
    +      NO_LOCALS = NOTHING,
    +      NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING });
    +  
    +
    +  /**
    +   * Studies a set of invocables that are likely to be used multiple times.
    +   *      $resolve.study(invocables)(locals, parent, self)
    +   * is equivalent to
    +   *      $resolve.resolve(invocables, locals, parent, self)
    +   * but the former is more efficient (in fact `resolve` just calls `study` internally).
    +   * See {@link module:$resolve/resolve} for details.
    +   * @function
    +   * @param {Object} invocables
    +   * @return {Function}
    +   */
    +  this.study = function (invocables) {
    +    if (!isObject(invocables)) throw new Error("'invocables' must be an object");
    +    
    +    // Perform a topological sort of invocables to build an ordered plan
    +    var plan = [], cycle = [], visited = {};
    +    function visit(value, key) {
    +      if (visited[key] === VISIT_DONE) return;
    +      
    +      cycle.push(key);
    +      if (visited[key] === VISIT_IN_PROGRESS) {
    +        cycle.splice(0, cycle.indexOf(key));
    +        throw new Error("Cyclic dependency: " + cycle.join(" -> "));
    +      }
    +      visited[key] = VISIT_IN_PROGRESS;
    +      
    +      if (isString(value)) {
    +        plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES);
    +      } else {
    +        var params = $injector.annotate(value);
    +        forEach(params, function (param) {
    +          if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param);
    +        });
    +        plan.push(key, value, params);
    +      }
    +      
    +      cycle.pop();
    +      visited[key] = VISIT_DONE;
    +    }
    +    forEach(invocables, visit);
    +    invocables = cycle = visited = null; // plan is all that's required
    +    
    +    function isResolve(value) {
    +      return isObject(value) && value.then && value.$$promises;
    +    }
    +    
    +    return function (locals, parent, self) {
    +      if (isResolve(locals) && self === undefined) {
    +        self = parent; parent = locals; locals = null;
    +      }
    +      if (!locals) locals = NO_LOCALS;
    +      else if (!isObject(locals)) {
    +        throw new Error("'locals' must be an object");
    +      }       
    +      if (!parent) parent = NO_PARENT;
    +      else if (!isResolve(parent)) {
    +        throw new Error("'parent' must be a promise returned by $resolve.resolve()");
    +      }
    +      
    +      // To complete the overall resolution, we have to wait for the parent
    +      // promise and for the promise for each invokable in our plan.
    +      var resolution = $q.defer(),
    +          result = resolution.promise,
    +          promises = result.$$promises = {},
    +          values = extend({}, locals),
    +          wait = 1 + plan.length/3,
    +          merged = false;
    +          
    +      function done() {
    +        // Merge parent values we haven't got yet and publish our own $$values
    +        if (!--wait) {
    +          if (!merged) merge(values, parent.$$values); 
    +          result.$$values = values;
    +          result.$$promises = true; // keep for isResolve()
    +          resolution.resolve(values);
    +        }
    +      }
    +      
    +      function fail(reason) {
    +        result.$$failure = reason;
    +        resolution.reject(reason);
    +      }
    +      
    +      // Short-circuit if parent has already failed
    +      if (isDefined(parent.$$failure)) {
    +        fail(parent.$$failure);
    +        return result;
    +      }
    +      
    +      // Merge parent values if the parent has already resolved, or merge
    +      // parent promises and wait if the parent resolve is still in progress.
    +      if (parent.$$values) {
    +        merged = merge(values, parent.$$values);
    +        done();
    +      } else {
    +        extend(promises, parent.$$promises);
    +        parent.then(done, fail);
    +      }
    +      
    +      // Process each invocable in the plan, but ignore any where a local of the same name exists.
    +      for (var i=0, ii=plan.length; i<ii; i+=3) {
    +        if (locals.hasOwnProperty(plan[i])) done();
    +        else invoke(plan[i], plan[i+1], plan[i+2]);
    +      }
    +      
    +      function invoke(key, invocable, params) {
    +        // Create a deferred for this invocation. Failures will propagate to the resolution as well.
    +        var invocation = $q.defer(), waitParams = 0;
    +        function onfailure(reason) {
    +          invocation.reject(reason);
    +          fail(reason);
    +        }
    +        // Wait for any parameter that we have a promise for (either from parent or from this
    +        // resolve; in that case study() will have made sure it's ordered before us in the plan).
    +        forEach(params, function (dep) {
    +          if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) {
    +            waitParams++;
    +            promises[dep].then(function (result) {
    +              values[dep] = result;
    +              if (!(--waitParams)) proceed();
    +            }, onfailure);
    +          }
    +        });
    +        if (!waitParams) proceed();
    +        function proceed() {
    +          if (isDefined(result.$$failure)) return;
    +          try {
    +            invocation.resolve($injector.invoke(invocable, self, values));
    +            invocation.promise.then(function (result) {
    +              values[key] = result;
    +              done();
    +            }, onfailure);
    +          } catch (e) {
    +            onfailure(e);
    +          }
    +        }
    +        // Publish promise synchronously; invocations further down in the plan may depend on it.
    +        promises[key] = invocation.promise;
    +      }
    +      
    +      return result;
    +    };
    +  };
    +  
    +  /**
    +   * Resolves a set of invocables. An invocable is a function to be invoked via `$injector.invoke()`,
    +   * and can have an arbitrary number of dependencies. An invocable can either return a value directly,
    +   * or a `$q` promise. If a promise is returned it will be resolved and the resulting value will be
    +   * used instead. Dependencies of invocables are resolved (in this order of precedence)
    +   *
    +   * - from the specified `locals`
    +   * - from another invocable that is part of this `$resolve` call
    +   * - from an invocable that is inherited from a `parent` call to `$resolve` (or recursively
    +   *   from any ancestor `$resolve` of that parent).
    +   *
    +   * The return value of `$resolve` is a promise for an object that contains (in this order of precedence)
    +   *
    +   * - any `locals` (if specified)
    +   * - the resolved return values of all injectables
    +   * - any values inherited from a `parent` call to `$resolve` (if specified)
    +   *
    +   * The promise will resolve after the `parent` promise (if any) and all promises returned by injectables
    +   * have been resolved. If any invocable (or `$injector.invoke`) throws an exception, or if a promise
    +   * returned by an invocable is rejected, the `$resolve` promise is immediately rejected with the same error.
    +   * A rejection of a `parent` promise (if specified) will likewise be propagated immediately. Once the
    +   * `$resolve` promise has been rejected, no further invocables will be called.
    +   * 
    +   * Cyclic dependencies between invocables are not permitted and will caues `$resolve` to throw an
    +   * error. As a special case, an injectable can depend on a parameter with the same name as the injectable,
    +   * which will be fulfilled from the `parent` injectable of the same name. This allows inherited values
    +   * to be decorated. Note that in this case any other injectable in the same `$resolve` with the same
    +   * dependency would see the decorated value, not the inherited value.
    +   *
    +   * Note that missing dependencies -- unlike cyclic dependencies -- will cause an (asynchronous) rejection
    +   * of the `$resolve` promise rather than a (synchronous) exception.
    +   *
    +   * Invocables are invoked eagerly as soon as all dependencies are available. This is true even for
    +   * dependencies inherited from a `parent` call to `$resolve`.
    +   *
    +   * As a special case, an invocable can be a string, in which case it is taken to be a service name
    +   * to be passed to `$injector.get()`. This is supported primarily for backwards-compatibility with the
    +   * `resolve` property of `$routeProvider` routes.
    +   *
    +   * @function
    +   * @param {Object.<string, Function|string>} invocables  functions to invoke or `$injector` services to fetch.
    +   * @param {Object.<string, *>} [locals]  values to make available to the injectables
    +   * @param {Promise.<Object>} [parent]  a promise returned by another call to `$resolve`.
    +   * @param {Object} [self]  the `this` for the invoked methods
    +   * @return {Promise.<Object>}  Promise for an object that contains the resolved return value
    +   *    of all invocables, as well as any inherited and local values.
    +   */
    +  this.resolve = function (invocables, locals, parent, self) {
    +    return this.study(invocables)(locals, parent, self);
    +  };
    +}
    +
    +angular.module('ui.router.util').service('$resolve', $Resolve);
    +
    +
    +
    +
    + + + + +
    + + + +
    + +
    + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST) +
    + + + + + diff --git a/release/doc/scripts/linenumber.js b/release/doc/scripts/linenumber.js new file mode 100644 index 000000000..613865d0e --- /dev/null +++ b/release/doc/scripts/linenumber.js @@ -0,0 +1,17 @@ +(function() { + var counter = 0; + var numbered; + var source = document.getElementsByClassName('prettyprint source'); + + if (source && source[0]) { + source = source[0].getElementsByTagName('code')[0]; + + numbered = source.innerHTML.split('\n'); + numbered = numbered.map(function(item) { + counter++; + return '' + item; + }); + + source.innerHTML = numbered.join('\n'); + } +})(); diff --git a/release/doc/styles/jsdoc-default.css b/release/doc/styles/jsdoc-default.css index ea49f6077..7afd6850a 100644 --- a/release/doc/styles/jsdoc-default.css +++ b/release/doc/styles/jsdoc-default.css @@ -195,12 +195,14 @@ h6 font-family: Consolas, "Lucida Console", Monaco, monospace; } -.details { margin-top: 14px; } -.details dt { width:100px; float:left; border-left: 2px solid #DDD; padding-left: 10px; padding-top: 6px; } +.details { margin-top: 14px; border-left: 2px solid #DDD; } +.details dt { width:100px; float:left; padding-left: 10px; padding-top: 6px; } .details dd { margin-left: 50px; } .details ul { margin: 0; } .details ul { list-style-type: none; } .details li { margin-left: 30px; padding-top: 6px; } +.details pre.prettyprint { margin: 0 } +.details .object-value { padding-top: 0; } .description { margin-bottom: 1em; @@ -240,6 +242,11 @@ h6 border-left: 3px #ddd solid; } +.prettyprint code span.line +{ + display: inline-block; +} + .params, .props { border-spacing: 0; diff --git a/release/doc/templateFactory.js.html b/release/doc/templateFactory.js.html new file mode 100644 index 000000000..4a1213db3 --- /dev/null +++ b/release/doc/templateFactory.js.html @@ -0,0 +1,137 @@ + + + + + JSDoc: Source: templateFactory.js + + + + + + + + + + +
    + +

    Source: templateFactory.js

    + + + + + +
    +
    +
    /**
    + * Service. Manages loading of templates.
    + * @constructor
    + * @name $templateFactory
    + * @requires $http
    + * @requires $templateCache
    + * @requires $injector
    + */
    +$TemplateFactory.$inject = ['$http', '$templateCache', '$injector'];
    +function $TemplateFactory(  $http,   $templateCache,   $injector) {
    +
    +  /**
    +   * Creates a template from a configuration object. 
    +   * @function
    +   * @name $templateFactory#fromConfig
    +   * @methodOf $templateFactory
    +   * @param {Object} config  Configuration object for which to load a template. The following
    +   *    properties are search in the specified order, and the first one that is defined is
    +   *    used to create the template:
    +   * @param {string|Function} config.template  html string template or function to load via
    +   *    {@link $templateFactory#fromString fromString}.
    +   * @param {string|Function} config.templateUrl  url to load or a function returning the url
    +   *    to load via {@link $templateFactory#fromUrl fromUrl}.
    +   * @param {Function} config.templateProvider  function to invoke via
    +   *    {@link $templateFactory#fromProvider fromProvider}.
    +   * @param {Object} params  Parameters to pass to the template function.
    +   * @param {Object} [locals] Locals to pass to `invoke` if the template is loaded via a
    +   *      `templateProvider`. Defaults to `{ params: params }`.
    +   * @return {string|Promise.<string>}  The template html as a string, or a promise for that string,
    +   *      or `null` if no template is configured.
    +   */
    +  this.fromConfig = function (config, params, locals) {
    +    return (
    +      isDefined(config.template) ? this.fromString(config.template, params) :
    +      isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
    +      isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
    +      null
    +    );
    +  };
    +
    +  /**
    +   * Creates a template from a string or a function returning a string.
    +   * @function
    +   * @name $templateFactory#fromString
    +   * @methodOf $templateFactory
    +   * @param {string|Function} template  html template as a string or function that returns an html
    +   *      template as a string.
    +   * @param {Object} params  Parameters to pass to the template function.
    +   * @return {string|Promise.<string>}  The template html as a string, or a promise for that string.
    +   */
    +  this.fromString = function (template, params) {
    +    return isFunction(template) ? template(params) : template;
    +  };
    +
    +  /**
    +   * Loads a template from the a URL via `$http` and `$templateCache`.
    +   * @function
    +   * @name $templateFactory#fromUrl
    +   * @methodOf $templateFactory
    +   * @param {string|Function} url  url of the template to load, or a function that returns a url.
    +   * @param {Object} params  Parameters to pass to the url function.
    +   * @return {string|Promise.<string>}  The template html as a string, or a promise for that string.
    +   */
    +  this.fromUrl = function (url, params) {
    +    if (isFunction(url)) url = url(params);
    +    if (url == null) return null;
    +    else return $http
    +        .get(url, { cache: $templateCache })
    +        .then(function(response) { return response.data; });
    +  };
    +
    +  /**
    +   * Creates a template by invoking an injectable provider function.
    +   * @function
    +   * @name $templateFactory#fromUrl
    +   * @methodOf $templateFactory
    +   * @param {Function} provider Function to invoke via `$injector.invoke`
    +   * @param {Object} params Parameters for the template.
    +   * @param {Object} [locals] Locals to pass to `invoke`. Defaults to `{ params: params }`.
    +   * @return {string|Promise.<string>} The template html as a string, or a promise for that string.
    +   */
    +  this.fromProvider = function (provider, params, locals) {
    +    return $injector.invoke(provider, null, locals || { params: params });
    +  };
    +}
    +
    +angular.module('ui.router.util').service('$templateFactory', $TemplateFactory);
    +
    +
    +
    + + + + +
    + + + +
    + +
    + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST) +
    + + + + + diff --git a/release/doc/urlMatcherFactory.js.html b/release/doc/urlMatcherFactory.js.html new file mode 100644 index 000000000..45dfb11b9 --- /dev/null +++ b/release/doc/urlMatcherFactory.js.html @@ -0,0 +1,306 @@ + + + + + JSDoc: Source: urlMatcherFactory.js + + + + + + + + + + +
    + +

    Source: urlMatcherFactory.js

    + + + + + +
    +
    +
    /**
    + * Matches URLs against patterns and extracts named parameters from the path or the search
    + * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list
    + * of search parameters. Multiple search parameter names are separated by '&'. Search parameters
    + * do not influence whether or not a URL is matched, but their values are passed through into
    + * the matched parameters returned by {@link UrlMatcher#exec exec}.
    + * 
    + * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace
    + * syntax, which optionally allows a regular expression for the parameter to be specified:
    + *
    + * * ':' name - colon placeholder
    + * * '*' name - catch-all placeholder
    + * * '{' name '}' - curly placeholder
    + * * '{' name ':' regexp '}' - curly placeholder with regexp. Should the regexp itself contain
    + *   curly braces, they must be in matched pairs or escaped with a backslash.
    + *
    + * Parameter names may contain only word characters (latin letters, digits, and underscore) and
    + * must be unique within the pattern (across both path and search parameters). For colon 
    + * placeholders or curly placeholders without an explicit regexp, a path parameter matches any
    + * number of characters other than '/'. For catch-all placeholders the path parameter matches
    + * any number of characters.
    + * 
    + * ### Examples
    + * 
    + * * '/hello/' - Matches only if the path is exactly '/hello/'. There is no special treatment for
    + *   trailing slashes, and patterns have to match the entire path, not just a prefix.
    + * * '/user/:id' - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
    + *   '/user/bob/details'. The second path segment will be captured as the parameter 'id'.
    + * * '/user/{id}' - Same as the previous example, but using curly brace syntax.
    + * * '/user/{id:[^/]*}' - Same as the previous example.
    + * * '/user/{id:[0-9a-fA-F]{1,8}}' - Similar to the previous example, but only matches if the id
    + *   parameter consists of 1 to 8 hex digits.
    + * * '/files/{path:.*}' - Matches any URL starting with '/files/' and captures the rest of the
    + *   path into the parameter 'path'.
    + * * '/files/*path' - ditto.
    + *
    + * @constructor
    + * @param {string} pattern  the pattern to compile into a matcher.
    + *
    + * @property {string} prefix  A static prefix of this pattern. The matcher guarantees that any
    + *   URL matching this matcher (i.e. any string for which {@link UrlMatcher#exec exec()} returns
    + *   non-null) will start with this prefix.
    + */
    +function UrlMatcher(pattern) {
    +
    +  // Find all placeholders and create a compiled pattern, using either classic or curly syntax:
    +  //   '*' name
    +  //   ':' name
    +  //   '{' name '}'
    +  //   '{' name ':' regexp '}'
    +  // The regular expression is somewhat complicated due to the need to allow curly braces
    +  // inside the regular expression. The placeholder regexp breaks down as follows:
    +  //    ([:*])(\w+)               classic placeholder ($1 / $2)
    +  //    \{(\w+)(?:\:( ... ))?\}   curly brace placeholder ($3) with optional regexp ... ($4)
    +  //    (?: ... | ... | ... )+    the regexp consists of any number of atoms, an atom being either
    +  //    [^{}\\]+                  - anything other than curly braces or backslash
    +  //    \\.                       - a backslash escape
    +  //    \{(?:[^{}\\]+|\\.)*\}     - a matched set of curly braces containing other atoms
    +  var placeholder = /([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
    +      names = {}, compiled = '^', last = 0, m,
    +      segments = this.segments = [],
    +      params = this.params = [];
    +
    +  function addParameter(id) {
    +    if (!/^\w+(-+\w+)*$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
    +    if (names[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
    +    names[id] = true;
    +    params.push(id);
    +  }
    +
    +  function quoteRegExp(string) {
    +    return string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&");
    +  }
    +
    +  this.source = pattern;
    +
    +  // Split into static segments separated by path parameter placeholders.
    +  // The number of segments is always 1 more than the number of parameters.
    +  var id, regexp, segment;
    +  while ((m = placeholder.exec(pattern))) {
    +    id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null
    +    regexp = m[4] || (m[1] == '*' ? '.*' : '[^/]*');
    +    segment = pattern.substring(last, m.index);
    +    if (segment.indexOf('?') >= 0) break; // we're into the search part
    +    compiled += quoteRegExp(segment) + '(' + regexp + ')';
    +    addParameter(id);
    +    segments.push(segment);
    +    last = placeholder.lastIndex;
    +  }
    +  segment = pattern.substring(last);
    +
    +  // Find any search parameter names and remove them from the last segment
    +  var i = segment.indexOf('?');
    +  if (i >= 0) {
    +    var search = this.sourceSearch = segment.substring(i);
    +    segment = segment.substring(0, i);
    +    this.sourcePath = pattern.substring(0, last+i);
    +
    +    // Allow parameters to be separated by '?' as well as '&' to make concat() easier
    +    forEach(search.substring(1).split(/[&?]/), addParameter);
    +  } else {
    +    this.sourcePath = pattern;
    +    this.sourceSearch = '';
    +  }
    +
    +  compiled += quoteRegExp(segment) + '$';
    +  segments.push(segment);
    +  this.regexp = new RegExp(compiled);
    +  this.prefix = segments[0];
    +}
    +
    +/**
    + * Returns a new matcher for a pattern constructed by appending the path part and adding the
    + * search parameters of the specified pattern to this pattern. The current pattern is not
    + * modified. This can be understood as creating a pattern for URLs that are relative to (or
    + * suffixes of) the current pattern.
    + *
    + * ### Example
    + * The following two matchers are equivalent:
    + * ```
    + * new UrlMatcher('/user/{id}?q').concat('/details?date');
    + * new UrlMatcher('/user/{id}/details?q&date');
    + * ```
    + *
    + * @param {string} pattern  The pattern to append.
    + * @return {UrlMatcher}  A matcher for the concatenated pattern.
    + */
    +UrlMatcher.prototype.concat = function (pattern) {
    +  // Because order of search parameters is irrelevant, we can add our own search
    +  // parameters to the end of the new pattern. Parse the new pattern by itself
    +  // and then join the bits together, but it's much easier to do this on a string level.
    +  return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch);
    +};
    +
    +UrlMatcher.prototype.toString = function () {
    +  return this.source;
    +};
    +
    +/**
    + * Tests the specified path against this matcher, and returns an object containing the captured
    + * parameter values, or null if the path does not match. The returned object contains the values
    + * of any search parameters that are mentioned in the pattern, but their value may be null if
    + * they are not present in `searchParams`. This means that search parameters are always treated
    + * as optional.
    + *
    + * ### Example
    + * ```
    + * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', { x:'1', q:'hello' });
    + * // returns { id:'bob', q:'hello', r:null }
    + * ```
    + *
    + * @param {string} path  The URL path to match, e.g. `$location.path()`.
    + * @param {Object} searchParams  URL search parameters, e.g. `$location.search()`.
    + * @return {Object}  The captured parameter values.
    + */
    +UrlMatcher.prototype.exec = function (path, searchParams) {
    +  var m = this.regexp.exec(path);
    +  if (!m) return null;
    +
    +  var params = this.params, nTotal = params.length,
    +    nPath = this.segments.length-1,
    +    values = {}, i;
    +
    +  if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'");
    +
    +  for (i=0; i<nPath; i++) values[params[i]] = m[i+1];
    +  for (/**/; i<nTotal; i++) values[params[i]] = searchParams[params[i]];
    +
    +  return values;
    +};
    +
    +/**
    + * Returns the names of all path and search parameters of this pattern in an unspecified order.
    + * @return {Array.<string>}  An array of parameter names. Must be treated as read-only. If the
    + *    pattern has no parameters, an empty array is returned.
    + */
    +UrlMatcher.prototype.parameters = function () {
    +  return this.params;
    +};
    +
    +/**
    + * Creates a URL that matches this pattern by substituting the specified values
    + * for the path and search parameters. Null values for path parameters are
    + * treated as empty strings.
    + *
    + * ### Example
    + * ```
    + * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
    + * // returns '/user/bob?q=yes'
    + * ```
    + *
    + * @param {Object} values  the values to substitute for the parameters in this pattern.
    + * @return {string}  the formatted URL (path and optionally search part).
    + */
    +UrlMatcher.prototype.format = function (values) {
    +  var segments = this.segments, params = this.params;
    +  if (!values) return segments.join('');
    +
    +  var nPath = segments.length-1, nTotal = params.length,
    +    result = segments[0], i, search, value;
    +
    +  for (i=0; i<nPath; i++) {
    +    value = values[params[i]];
    +    // TODO: Maybe we should throw on null here? It's not really good style to use '' and null interchangeabley
    +    if (value != null) result += encodeURIComponent(value);
    +    result += segments[i+1];
    +  }
    +  for (/**/; i<nTotal; i++) {
    +    value = values[params[i]];
    +    if (value != null) {
    +      result += (search ? '&' : '?') + params[i] + '=' + encodeURIComponent(value);
    +      search = true;
    +    }
    +  }
    +
    +  return result;
    +};
    +
    +/**
    + * Service. Factory for {@link UrlMatcher} instances. The factory is also available to providers
    + * under the name `$urlMatcherFactoryProvider`.
    + * @constructor
    + * @name $urlMatcherFactory
    + */
    +function $UrlMatcherFactory() {
    +  /**
    +   * Creates a {@link UrlMatcher} for the specified pattern.
    +   * @function
    +   * @name $urlMatcherFactory#compile
    +   * @methodOf $urlMatcherFactory
    +   * @param {string} pattern  The URL pattern.
    +   * @return {UrlMatcher}  The UrlMatcher.
    +   */
    +  this.compile = function (pattern) {
    +    return new UrlMatcher(pattern);
    +  };
    +
    +  /**
    +   * Returns true if the specified object is a UrlMatcher, or false otherwise.
    +   * @function
    +   * @name $urlMatcherFactory#isMatcher
    +   * @methodOf $urlMatcherFactory
    +   * @param {Object} o
    +   * @return {boolean}
    +   */
    +  this.isMatcher = function (o) {
    +    return isObject(o) && isFunction(o.exec) && isFunction(o.format) && isFunction(o.concat);
    +  };
    +
    +  this.$get = function () {
    +    return this;
    +  };
    +}
    +
    +// Register as a provider so it's available to other providers
    +angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory);
    +
    +
    +
    + + + + +
    + + + +
    + +
    + Documentation generated by JSDoc 3.2.2 on Fri Dec 06 2013 14:17:59 GMT-0500 (EST) +
    + + + + +