From 52df401082b78771f338e2adc679597b9ddd1948 Mon Sep 17 00:00:00 2001 From: Davide Alberani Date: Sun, 10 Apr 2016 11:57:01 +0200 Subject: [PATCH] fixes #84: updates angular-ui-router --- static/js/angular-ui-router.js | 12167 +++++++++++++++++---------- static/js/angular-ui-router.min.js | 12 +- 2 files changed, 7638 insertions(+), 4541 deletions(-) diff --git a/static/js/angular-ui-router.js b/static/js/angular-ui-router.js index 26f7657..6b10559 100644 --- a/static/js/angular-ui-router.js +++ b/static/js/angular-ui-router.js @@ -1,4539 +1,7634 @@ -/** +/*! * State-based routing for AngularJS - * @version v0.2.18 - * @link http://angular-ui.github.com/ + * @version v1.0.0-alpha.4 + * @link http://angular-ui.github.com/ui-router * @license MIT License, http://www.opensource.org/licenses/MIT */ - -/* commonjs package manager support (eg componentjs) */ -if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports){ - module.exports = 'ui.router'; -} - -(function (window, angular, undefined) { -/*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, - toJson = angular.toJson; - -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] !== 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 objectKeys(object) { - if (Object.keys) { - return Object.keys(object); - } - var result = []; - - 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 indexOf(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] || !parents[i].params) continue; - parentParams = objectKeys(parents[i].params); - if (!parentParams.length) continue; - - for (var j in parentParams) { - if (indexOf(inheritList, parentParams[j]) >= 0) continue; - inheritList.push(parentParams[j]); - inherited[parentParams[j]] = currentParams[parentParams[j]]; - } - } - return extend({}, inherited, newParams); -} - -/** - * 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 - * - * - * - * - * - * - * - * - * - * - * - * - */ -angular.module('ui.router', ['ui.router.state']); - -angular.module('ui.router.compat', ['ui.router']); - -/** - * @ngdoc object - * @name ui.router.util.$resolve - * - * @requires $q - * @requires $injector - * - * @description - * Manages resolution of (acyclic) graphs of promises. - */ -$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 }); - - - /** - * @ngdoc function - * @name ui.router.util.$resolve#study - * @methodOf ui.router.util.$resolve - * - * @description - * 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). - * - * @param {object} invocables Invocable objects - * @return {function} a function to pass in locals, parent and self - */ - this.study = function (invocables) { - if (!isObject(invocables)) throw new Error("'invocables' must be an object"); - var invocableKeys = objectKeys(invocables || {}); - - // 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, indexOf(cycle, 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 = result.$$promises || true; // keep for isResolve() - delete result.$$inheritedValues; - 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; - } - - if (parent.$$inheritedValues) { - merge(values, omit(parent.$$inheritedValues, invocableKeys)); - } - - // Merge parent values if the parent has already resolved, or merge - // parent promises and wait if the parent resolve is still in progress. - extend(promises, parent.$$promises); - if (parent.$$values) { - merged = merge(values, omit(parent.$$values, invocableKeys)); - result.$$inheritedValues = omit(parent.$$values, invocableKeys); - done(); - } else { - if (parent.$$inheritedValues) { - result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys); - } - 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} 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, headers: { Accept: 'text/html' }}) - .then(function(response) { return response.data; }); - }; - - /** - * @ngdoc function - * @name ui.router.util.$templateFactory#fromProvider - * @methodOf ui.router.util.$templateFactory - * - * @description - * Creates a template by invoking an injectable provider function. - * - * @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.} 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); - -var $$UMFP; // reference to $UrlMatcherFactoryProvider - -/** - * @ngdoc object - * @name ui.router.util.type:UrlMatcher - * - * @description - * 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 ui.router.util.type:UrlMatcher#methods_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|type '}'` - curly placeholder with regexp or type name. 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. - * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined - * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start - * - * @param {string} pattern The pattern to compile into a matcher. - * @param {Object} config A configuration object hash: - * @param {Object=} parentMatcher Used to concatenate the pattern/config onto - * an existing UrlMatcher - * - * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`. - * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`. - * - * @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 ui.router.util.type:UrlMatcher#methods_exec exec()} returns - * non-null) will start with this prefix. - * - * @property {string} source The pattern that was passed into the constructor - * - * @property {string} sourcePath The path portion of the source property - * - * @property {string} sourceSearch The search portion of the source property - * - * @property {string} regex The constructed regex that will be used to match against the url when - * it is time to determine which url will match. - * - * @returns {Object} New `UrlMatcher` object - */ -function UrlMatcher(pattern, config, parentMatcher) { - config = extend({ params: {} }, isObject(config) ? config : {}); - - // 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) (search version has - for snake-case) - // \{([\w\[\]]+)(?:\:\s*( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case - // (?: ... | ... | ... )+ - 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\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, - searchPlaceholder = /([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, - compiled = '^', last = 0, m, - segments = this.segments = [], - parentParams = parentMatcher ? parentMatcher.params : {}, - params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(), - paramNames = []; - - function addParameter(id, type, config, location) { - paramNames.push(id); - if (parentParams[id]) return parentParams[id]; - if (!/^\w+([-.]+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'"); - if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'"); - params[id] = new $$UMFP.Param(id, type, config, location); - return params[id]; - } - - function quoteRegExp(string, pattern, squash, optional) { - var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&"); - if (!pattern) return result; - switch(squash) { - case false: surroundPattern = ['(', ')' + (optional ? "?" : "")]; break; - case true: - result = result.replace(/\/$/, ''); - surroundPattern = ['(?:\/(', ')|\/)?']; - break; - default: surroundPattern = ['(' + squash + "|", ')?']; break; - } - return result + surroundPattern[0] + pattern + surroundPattern[1]; - } - - 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. - function matchDetails(m, isSearch) { - var id, regexp, segment, type, cfg, arrayMode; - id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null - cfg = config.params[id]; - segment = pattern.substring(last, m.index); - regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null); - - if (regexp) { - type = $$UMFP.type(regexp) || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp, config.caseInsensitive ? 'i' : undefined) }); - } - - return { - id: id, regexp: regexp, segment: segment, type: type, cfg: cfg - }; - } - - var p, param, segment; - while ((m = placeholder.exec(pattern))) { - p = matchDetails(m, false); - if (p.segment.indexOf('?') >= 0) break; // we're into the search part - - param = addParameter(p.id, p.type, p.cfg, "path"); - compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash, param.isOptional); - segments.push(p.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); - - if (search.length > 0) { - last = 0; - while ((m = searchPlaceholder.exec(search))) { - p = matchDetails(m, true); - param = addParameter(p.id, p.type, p.cfg, "search"); - last = placeholder.lastIndex; - // check if ?& - } - } - } else { - this.sourcePath = pattern; - this.sourceSearch = ''; - } - - compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$'; - segments.push(segment); - - this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined); - this.prefix = segments[0]; - this.$$paramNames = paramNames; -} - -/** - * @ngdoc function - * @name ui.router.util.type:UrlMatcher#concat - * @methodOf ui.router.util.type:UrlMatcher - * - * @description - * 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. - * @param {Object} config An object hash of the configuration for the matcher. - * @returns {UrlMatcher} A matcher for the concatenated pattern. - */ -UrlMatcher.prototype.concat = function (pattern, config) { - // 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. - var defaultConfig = { - caseInsensitive: $$UMFP.caseInsensitive(), - strict: $$UMFP.strictMode(), - squash: $$UMFP.defaultSquashPolicy() - }; - return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this); -}; - -UrlMatcher.prototype.toString = function () { - return this.source; -}; - -/** - * @ngdoc function - * @name ui.router.util.type:UrlMatcher#exec - * @methodOf ui.router.util.type:UrlMatcher - * - * @description - * 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()`. - * @returns {Object} The captured parameter values. - */ -UrlMatcher.prototype.exec = function (path, searchParams) { - var m = this.regexp.exec(path); - if (!m) return null; - searchParams = searchParams || {}; - - var paramNames = this.parameters(), nTotal = paramNames.length, - nPath = this.segments.length - 1, - values = {}, i, j, cfg, paramName; - - if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'"); - - function decodePathArray(string) { - function reverseString(str) { return str.split("").reverse().join(""); } - function unquoteDashes(str) { return str.replace(/\\-/g, "-"); } - - var split = reverseString(string).split(/-(?!\\)/); - var allReversed = map(split, reverseString); - return map(allReversed, unquoteDashes).reverse(); - } - - var param, paramVal; - for (i = 0; i < nPath; i++) { - paramName = paramNames[i]; - param = this.params[paramName]; - paramVal = m[i+1]; - // if the param value matches a pre-replace pair, replace the value before decoding. - for (j = 0; j < param.replace.length; j++) { - if (param.replace[j].from === paramVal) paramVal = param.replace[j].to; - } - if (paramVal && param.array === true) paramVal = decodePathArray(paramVal); - if (isDefined(paramVal)) paramVal = param.type.decode(paramVal); - values[paramName] = param.value(paramVal); - } - for (/**/; i < nTotal; i++) { - paramName = paramNames[i]; - values[paramName] = this.params[paramName].value(searchParams[paramName]); - param = this.params[paramName]; - paramVal = searchParams[paramName]; - for (j = 0; j < param.replace.length; j++) { - if (param.replace[j].from === paramVal) paramVal = param.replace[j].to; - } - if (isDefined(paramVal)) paramVal = param.type.decode(paramVal); - values[paramName] = param.value(paramVal); - } - - return values; -}; - -/** - * @ngdoc function - * @name ui.router.util.type:UrlMatcher#parameters - * @methodOf ui.router.util.type:UrlMatcher - * - * @description - * Returns the names of all path and search parameters of this pattern in an unspecified order. - * - * @returns {Array.} 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 (param) { - if (!isDefined(param)) return this.$$paramNames; - return this.params[param] || null; -}; - -/** - * @ngdoc function - * @name ui.router.util.type:UrlMatcher#validates - * @methodOf ui.router.util.type:UrlMatcher - * - * @description - * Checks an object hash of parameters to validate their correctness according to the parameter - * types of this `UrlMatcher`. - * - * @param {Object} params The object hash of parameters to validate. - * @returns {boolean} Returns `true` if `params` validates, otherwise `false`. - */ -UrlMatcher.prototype.validates = function (params) { - return this.params.$$validates(params); -}; - -/** - * @ngdoc function - * @name ui.router.util.type:UrlMatcher#format - * @methodOf ui.router.util.type:UrlMatcher - * - * @description - * 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. - * @returns {string} the formatted URL (path and optionally search part). - */ -UrlMatcher.prototype.format = function (values) { - values = values || {}; - var segments = this.segments, params = this.parameters(), paramset = this.params; - if (!this.validates(values)) return null; - - var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0]; - - function encodeDashes(str) { // Replace dashes with encoded "\-" - return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); }); - } - - for (i = 0; i < nTotal; i++) { - var isPathParam = i < nPath; - var name = params[i], param = paramset[name], value = param.value(values[name]); - var isDefaultValue = param.isOptional && param.type.equals(param.value(), value); - var squash = isDefaultValue ? param.squash : false; - var encoded = param.type.encode(value); - - if (isPathParam) { - var nextSegment = segments[i + 1]; - var isFinalPathParam = i + 1 === nPath; - - if (squash === false) { - if (encoded != null) { - if (isArray(encoded)) { - result += map(encoded, encodeDashes).join("-"); - } else { - result += encodeURIComponent(encoded); - } - } - result += nextSegment; - } else if (squash === true) { - var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/; - result += nextSegment.match(capture)[1]; - } else if (isString(squash)) { - result += squash + nextSegment; - } - - if (isFinalPathParam && param.squash === true && result.slice(-1) === '/') result = result.slice(0, -1); - } else { - if (encoded == null || (isDefaultValue && squash !== false)) continue; - if (!isArray(encoded)) encoded = [ encoded ]; - if (encoded.length === 0) continue; - encoded = map(encoded, encodeURIComponent).join('&' + name + '='); - result += (search ? '&' : '?') + (name + '=' + encoded); - search = true; - } - } - - return result; -}; - -/** - * @ngdoc object - * @name ui.router.util.type:Type - * - * @description - * Implements an interface to define custom parameter types that can be decoded from and encoded to - * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`} - * objects when matching or formatting URLs, or comparing or validating parameter values. - * - * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more - * information on registering custom types. - * - * @param {Object} config A configuration object which contains the custom type definition. The object's - * properties will override the default methods and/or pattern in `Type`'s public interface. - * @example - *
- * {
- *   decode: function(val) { return parseInt(val, 10); },
- *   encode: function(val) { return val && val.toString(); },
- *   equals: function(a, b) { return this.is(a) && a === b; },
- *   is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
- *   pattern: /\d+/
- * }
- * 
- * - * @property {RegExp} pattern The regular expression pattern used to match values of this type when - * coming from a substring of a URL. - * - * @returns {Object} Returns a new `Type` object. - */ -function Type(config) { - extend(this, config); -} - -/** - * @ngdoc function - * @name ui.router.util.type:Type#is - * @methodOf ui.router.util.type:Type - * - * @description - * Detects whether a value is of a particular type. Accepts a native (decoded) value - * and determines whether it matches the current `Type` object. - * - * @param {*} val The value to check. - * @param {string} key Optional. If the type check is happening in the context of a specific - * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the - * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects. - * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`. - */ -Type.prototype.is = function(val, key) { - return true; -}; - -/** - * @ngdoc function - * @name ui.router.util.type:Type#encode - * @methodOf ui.router.util.type:Type - * - * @description - * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the - * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it - * only needs to be a representation of `val` that has been coerced to a string. - * - * @param {*} val The value to encode. - * @param {string} key The name of the parameter in which `val` is stored. Can be used for - * meta-programming of `Type` objects. - * @returns {string} Returns a string representation of `val` that can be encoded in a URL. - */ -Type.prototype.encode = function(val, key) { - return val; -}; - -/** - * @ngdoc function - * @name ui.router.util.type:Type#decode - * @methodOf ui.router.util.type:Type - * - * @description - * Converts a parameter value (from URL string or transition param) to a custom/native value. - * - * @param {string} val The URL parameter value to decode. - * @param {string} key The name of the parameter in which `val` is stored. Can be used for - * meta-programming of `Type` objects. - * @returns {*} Returns a custom representation of the URL parameter value. - */ -Type.prototype.decode = function(val, key) { - return val; -}; - -/** - * @ngdoc function - * @name ui.router.util.type:Type#equals - * @methodOf ui.router.util.type:Type - * - * @description - * Determines whether two decoded values are equivalent. - * - * @param {*} a A value to compare against. - * @param {*} b A value to compare against. - * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`. - */ -Type.prototype.equals = function(a, b) { - return a == b; -}; - -Type.prototype.$subPattern = function() { - var sub = this.pattern.toString(); - return sub.substr(1, sub.length - 2); -}; - -Type.prototype.pattern = /.*/; - -Type.prototype.toString = function() { return "{Type:" + this.name + "}"; }; - -/** Given an encoded string, or a decoded object, returns a decoded object */ -Type.prototype.$normalize = function(val) { - return this.is(val) ? val : this.decode(val); -}; - -/* - * Wraps an existing custom Type as an array of Type, depending on 'mode'. - * e.g.: - * - urlmatcher pattern "/path?{queryParam[]:int}" - * - url: "/path?queryParam=1&queryParam=2 - * - $stateParams.queryParam will be [1, 2] - * if `mode` is "auto", then - * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1 - * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2] - */ -Type.prototype.$asArray = function(mode, isSearch) { - if (!mode) return this; - if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only"); - - function ArrayType(type, mode) { - function bindTo(type, callbackName) { - return function() { - return type[callbackName].apply(type, arguments); - }; - } - - // Wrap non-array value as array - function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); } - // Unwrap array value for "auto" mode. Return undefined for empty array. - function arrayUnwrap(val) { - switch(val.length) { - case 0: return undefined; - case 1: return mode === "auto" ? val[0] : val; - default: return val; - } - } - function falsey(val) { return !val; } - - // Wraps type (.is/.encode/.decode) functions to operate on each value of an array - function arrayHandler(callback, allTruthyMode) { - return function handleArray(val) { - if (isArray(val) && val.length === 0) return val; - val = arrayWrap(val); - var result = map(val, callback); - if (allTruthyMode === true) - return filter(result, falsey).length === 0; - return arrayUnwrap(result); - }; - } - - // Wraps type (.equals) functions to operate on each value of an array - function arrayEqualsHandler(callback) { - return function handleArray(val1, val2) { - var left = arrayWrap(val1), right = arrayWrap(val2); - if (left.length !== right.length) return false; - for (var i = 0; i < left.length; i++) { - if (!callback(left[i], right[i])) return false; - } - return true; - }; - } - - this.encode = arrayHandler(bindTo(type, 'encode')); - this.decode = arrayHandler(bindTo(type, 'decode')); - this.is = arrayHandler(bindTo(type, 'is'), true); - this.equals = arrayEqualsHandler(bindTo(type, 'equals')); - this.pattern = type.pattern; - this.$normalize = arrayHandler(bindTo(type, '$normalize')); - this.name = type.name; - this.$arrayMode = mode; - } - - return new ArrayType(this, mode); -}; - - - -/** - * @ngdoc object - * @name ui.router.util.$urlMatcherFactory - * - * @description - * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory - * is also available to providers under the name `$urlMatcherFactoryProvider`. - */ -function $UrlMatcherFactory() { - $$UMFP = this; - - var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false; - - // Use tildes to pre-encode slashes. - // If the slashes are simply URLEncoded, the browser can choose to pre-decode them, - // and bidirectional encoding/decoding fails. - // Tilde was chosen because it's not a RFC 3986 section 2.2 Reserved Character - function valToString(val) { return val != null ? val.toString().replace(/~/g, "~~").replace(/\//g, "~2F") : val; } - function valFromString(val) { return val != null ? val.toString().replace(/~2F/g, "/").replace(/~~/g, "~") : val; } - - var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = { - "string": { - encode: valToString, - decode: valFromString, - // TODO: in 1.0, make string .is() return false if value is undefined/null by default. - // In 0.2.x, string params are optional by default for backwards compat - is: function(val) { return val == null || !isDefined(val) || typeof val === "string"; }, - pattern: /[^/]*/ - }, - "int": { - encode: valToString, - decode: function(val) { return parseInt(val, 10); }, - is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; }, - pattern: /\d+/ - }, - "bool": { - encode: function(val) { return val ? 1 : 0; }, - decode: function(val) { return parseInt(val, 10) !== 0; }, - is: function(val) { return val === true || val === false; }, - pattern: /0|1/ - }, - "date": { - encode: function (val) { - if (!this.is(val)) - return undefined; - return [ val.getFullYear(), - ('0' + (val.getMonth() + 1)).slice(-2), - ('0' + val.getDate()).slice(-2) - ].join("-"); - }, - decode: function (val) { - if (this.is(val)) return val; - var match = this.capture.exec(val); - return match ? new Date(match[1], match[2] - 1, match[3]) : undefined; - }, - is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); }, - equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); }, - pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/, - capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/ - }, - "json": { - encode: angular.toJson, - decode: angular.fromJson, - is: angular.isObject, - equals: angular.equals, - pattern: /[^/]*/ - }, - "any": { // does not encode/decode - encode: angular.identity, - decode: angular.identity, - equals: angular.equals, - pattern: /.*/ - } - }; - - function getDefaultConfig() { - return { - strict: isStrictMode, - caseInsensitive: isCaseInsensitive - }; - } - - function isInjectable(value) { - return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1]))); - } - - /** - * [Internal] Get the default value of a parameter, which may be an injectable function. - */ - $UrlMatcherFactory.$$getDefaultValue = function(config) { - if (!isInjectable(config.value)) return config.value; - if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); - return injector.invoke(config.value); - }; - - /** - * @ngdoc function - * @name ui.router.util.$urlMatcherFactory#caseInsensitive - * @methodOf ui.router.util.$urlMatcherFactory - * - * @description - * Defines whether URL matching should be case sensitive (the default behavior), or not. - * - * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`; - * @returns {boolean} the current value of caseInsensitive - */ - this.caseInsensitive = function(value) { - if (isDefined(value)) - isCaseInsensitive = value; - return isCaseInsensitive; - }; - - /** - * @ngdoc function - * @name ui.router.util.$urlMatcherFactory#strictMode - * @methodOf ui.router.util.$urlMatcherFactory - * - * @description - * Defines whether URLs should match trailing slashes, or not (the default behavior). - * - * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`. - * @returns {boolean} the current value of strictMode - */ - this.strictMode = function(value) { - if (isDefined(value)) - isStrictMode = value; - return isStrictMode; - }; - - /** - * @ngdoc function - * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy - * @methodOf ui.router.util.$urlMatcherFactory - * - * @description - * Sets the default behavior when generating or matching URLs with default parameter values. - * - * @param {string} value A string that defines the default parameter URL squashing behavior. - * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL - * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the - * parameter is surrounded by slashes, squash (remove) one slash from the URL - * any other string, e.g. "~": When generating an href with a default parameter value, squash (remove) - * the parameter value from the URL and replace it with this string. - */ - this.defaultSquashPolicy = function(value) { - if (!isDefined(value)) return defaultSquashPolicy; - if (value !== true && value !== false && !isString(value)) - throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string"); - defaultSquashPolicy = value; - return value; - }; - - /** - * @ngdoc function - * @name ui.router.util.$urlMatcherFactory#compile - * @methodOf ui.router.util.$urlMatcherFactory - * - * @description - * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern. - * - * @param {string} pattern The URL pattern. - * @param {Object} config The config object hash. - * @returns {UrlMatcher} The UrlMatcher. - */ - this.compile = function (pattern, config) { - return new UrlMatcher(pattern, extend(getDefaultConfig(), config)); - }; - - /** - * @ngdoc function - * @name ui.router.util.$urlMatcherFactory#isMatcher - * @methodOf ui.router.util.$urlMatcherFactory - * - * @description - * Returns true if the specified object is a `UrlMatcher`, or false otherwise. - * - * @param {Object} object The object to perform the type check against. - * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by - * implementing all the same methods. - */ - this.isMatcher = function (o) { - if (!isObject(o)) return false; - var result = true; - - forEach(UrlMatcher.prototype, function(val, name) { - if (isFunction(val)) { - result = result && (isDefined(o[name]) && isFunction(o[name])); - } - }); - return result; - }; - - /** - * @ngdoc function - * @name ui.router.util.$urlMatcherFactory#type - * @methodOf ui.router.util.$urlMatcherFactory - * - * @description - * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to - * generate URLs with typed parameters. - * - * @param {string} name The type name. - * @param {Object|Function} definition The type definition. See - * {@link ui.router.util.type:Type `Type`} for information on the values accepted. - * @param {Object|Function} definitionFn (optional) A function that is injected before the app - * runtime starts. The result of this function is merged into the existing `definition`. - * See {@link ui.router.util.type:Type `Type`} for information on the values accepted. - * - * @returns {Object} Returns `$urlMatcherFactoryProvider`. - * - * @example - * This is a simple example of a custom type that encodes and decodes items from an - * array, using the array index as the URL-encoded value: - * - *
-   * var list = ['John', 'Paul', 'George', 'Ringo'];
-   *
-   * $urlMatcherFactoryProvider.type('listItem', {
-   *   encode: function(item) {
-   *     // Represent the list item in the URL using its corresponding index
-   *     return list.indexOf(item);
-   *   },
-   *   decode: function(item) {
-   *     // Look up the list item by index
-   *     return list[parseInt(item, 10)];
-   *   },
-   *   is: function(item) {
-   *     // Ensure the item is valid by checking to see that it appears
-   *     // in the list
-   *     return list.indexOf(item) > -1;
-   *   }
-   * });
-   *
-   * $stateProvider.state('list', {
-   *   url: "/list/{item:listItem}",
-   *   controller: function($scope, $stateParams) {
-   *     console.log($stateParams.item);
-   *   }
-   * });
-   *
-   * // ...
-   *
-   * // Changes URL to '/list/3', logs "Ringo" to the console
-   * $state.go('list', { item: "Ringo" });
-   * 
- * - * This is a more complex example of a type that relies on dependency injection to - * interact with services, and uses the parameter name from the URL to infer how to - * handle encoding and decoding parameter values: - * - *
-   * // Defines a custom type that gets a value from a service,
-   * // where each service gets different types of values from
-   * // a backend API:
-   * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
-   *
-   *   // Matches up services to URL parameter names
-   *   var services = {
-   *     user: Users,
-   *     post: Posts
-   *   };
-   *
-   *   return {
-   *     encode: function(object) {
-   *       // Represent the object in the URL using its unique ID
-   *       return object.id;
-   *     },
-   *     decode: function(value, key) {
-   *       // Look up the object by ID, using the parameter
-   *       // name (key) to call the correct service
-   *       return services[key].findById(value);
-   *     },
-   *     is: function(object, key) {
-   *       // Check that object is a valid dbObject
-   *       return angular.isObject(object) && object.id && services[key];
-   *     }
-   *     equals: function(a, b) {
-   *       // Check the equality of decoded objects by comparing
-   *       // their unique IDs
-   *       return a.id === b.id;
-   *     }
-   *   };
-   * });
-   *
-   * // In a config() block, you can then attach URLs with
-   * // type-annotated parameters:
-   * $stateProvider.state('users', {
-   *   url: "/users",
-   *   // ...
-   * }).state('users.item', {
-   *   url: "/{user:dbObject}",
-   *   controller: function($scope, $stateParams) {
-   *     // $stateParams.user will now be an object returned from
-   *     // the Users service
-   *   },
-   *   // ...
-   * });
-   * 
- */ - this.type = function (name, definition, definitionFn) { - if (!isDefined(definition)) return $types[name]; - if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined."); - - $types[name] = new Type(extend({ name: name }, definition)); - if (definitionFn) { - typeQueue.push({ name: name, def: definitionFn }); - if (!enqueue) flushTypeQueue(); - } - return this; - }; - - // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s - function flushTypeQueue() { - while(typeQueue.length) { - var type = typeQueue.shift(); - if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime."); - angular.extend($types[type.name], injector.invoke(type.def)); - } - } - - // Register default types. Store them in the prototype of $types. - forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); }); - $types = inherit($types, {}); - - /* No need to document $get, since it returns this */ - this.$get = ['$injector', function ($injector) { - injector = $injector; - enqueue = false; - flushTypeQueue(); - - forEach(defaultTypes, function(type, name) { - if (!$types[name]) $types[name] = new Type(type); - }); - return this; - }]; - - this.Param = function Param(id, type, config, location) { - var self = this; - config = unwrapShorthand(config); - type = getType(config, type, location); - var arrayMode = getArrayMode(); - type = arrayMode ? type.$asArray(arrayMode, location === "search") : type; - if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined) - config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to "" - var isOptional = config.value !== undefined; - var squash = getSquashPolicy(config, isOptional); - var replace = getReplace(config, arrayMode, isOptional, squash); - - function unwrapShorthand(config) { - var keys = isObject(config) ? objectKeys(config) : []; - var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 && - indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1; - if (isShorthand) config = { value: config }; - config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; }; - return config; - } - - function getType(config, urlType, location) { - if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations."); - if (urlType) return urlType; - if (!config.type) return (location === "config" ? $types.any : $types.string); - - if (angular.isString(config.type)) - return $types[config.type]; - if (config.type instanceof Type) - return config.type; - return new Type(config.type); - } - - // array config: param name (param[]) overrides default settings. explicit config overrides param name. - function getArrayMode() { - var arrayDefaults = { array: (location === "search" ? "auto" : false) }; - var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {}; - return extend(arrayDefaults, arrayParamNomenclature, config).array; - } - - /** - * returns false, true, or the squash value to indicate the "default parameter url squash policy". - */ - function getSquashPolicy(config, isOptional) { - var squash = config.squash; - if (!isOptional || squash === false) return false; - if (!isDefined(squash) || squash == null) return defaultSquashPolicy; - if (squash === true || isString(squash)) return squash; - throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string"); - } - - function getReplace(config, arrayMode, isOptional, squash) { - var replace, configuredKeys, defaultPolicy = [ - { from: "", to: (isOptional || arrayMode ? undefined : "") }, - { from: null, to: (isOptional || arrayMode ? undefined : "") } - ]; - replace = isArray(config.replace) ? config.replace : []; - if (isString(squash)) - replace.push({ from: squash, to: undefined }); - configuredKeys = map(replace, function(item) { return item.from; } ); - return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace); - } - - /** - * [Internal] Get the default value of a parameter, which may be an injectable function. - */ - function $$getDefaultValue() { - if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); - var defaultValue = injector.invoke(config.$$fn); - if (defaultValue !== null && defaultValue !== undefined && !self.type.is(defaultValue)) - throw new Error("Default value (" + defaultValue + ") for parameter '" + self.id + "' is not an instance of Type (" + self.type.name + ")"); - return defaultValue; - } - - /** - * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the - * default value, which may be the result of an injectable function. - */ - function $value(value) { - function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; } - function $replace(value) { - var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; }); - return replacement.length ? replacement[0] : value; - } - value = $replace(value); - return !isDefined(value) ? $$getDefaultValue() : self.type.$normalize(value); - } - - function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; } - - extend(this, { - id: id, - type: type, - location: location, - array: arrayMode, - squash: squash, - replace: replace, - isOptional: isOptional, - value: $value, - dynamic: undefined, - config: config, - toString: toString - }); - }; - - function ParamSet(params) { - extend(this, params || {}); - } - - ParamSet.prototype = { - $$new: function() { - return inherit(this, extend(new ParamSet(), { $$parent: this})); - }, - $$keys: function () { - var keys = [], chain = [], parent = this, - ignore = objectKeys(ParamSet.prototype); - while (parent) { chain.push(parent); parent = parent.$$parent; } - chain.reverse(); - forEach(chain, function(paramset) { - forEach(objectKeys(paramset), function(key) { - if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key); - }); - }); - return keys; - }, - $$values: function(paramValues) { - var values = {}, self = this; - forEach(self.$$keys(), function(key) { - values[key] = self[key].value(paramValues && paramValues[key]); - }); - return values; - }, - $$equals: function(paramValues1, paramValues2) { - var equal = true, self = this; - forEach(self.$$keys(), function(key) { - var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key]; - if (!self[key].type.equals(left, right)) equal = false; - }); - return equal; - }, - $$validates: function $$validate(paramValues) { - var keys = this.$$keys(), i, param, rawVal, normalized, encoded; - for (i = 0; i < keys.length; i++) { - param = this[keys[i]]; - rawVal = paramValues[keys[i]]; - if ((rawVal === undefined || rawVal === null) && param.isOptional) - break; // There was no parameter value, but the param is optional - normalized = param.type.$normalize(rawVal); - if (!param.type.is(normalized)) - return false; // The value was not of the correct Type, and could not be decoded to the correct Type - encoded = param.type.encode(normalized); - if (angular.isString(encoded) && !param.type.pattern.exec(encoded)) - return false; // The value was of the correct type, but when encoded, did not match the Type's regexp - } - return true; - }, - $$parent: undefined - }; - - this.ParamSet = ParamSet; -} - -// Register as a provider so it's available to other providers -angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory); -angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]); - -/** - * @ngdoc object - * @name ui.router.router.$urlRouterProvider - * - * @requires ui.router.util.$urlMatcherFactoryProvider - * @requires $locationProvider - * - * @description - * `$urlRouterProvider` has the responsibility of watching `$location`. - * When `$location` changes it runs through a list of rules one by one until a - * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify - * a url in a state configuration. All urls are compiled into a UrlMatcher object. - * - * There are several methods on `$urlRouterProvider` that make it useful to use directly - * in your module config. - */ -$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider']; -function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) { - var rules = [], otherwise = null, interceptDeferred = false, listener; - - // Returns a string that is a prefix of all strings matching the RegExp - function regExpPrefix(re) { - var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source); - return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : ''; - } - - // Interpolates matched values into a String.replace()-style pattern - function interpolate(pattern, match) { - return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) { - return match[what === '$' ? 0 : Number(what)]; - }); - } - - /** - * @ngdoc function - * @name ui.router.router.$urlRouterProvider#rule - * @methodOf ui.router.router.$urlRouterProvider - * - * @description - * Defines rules that are used by `$urlRouterProvider` to find matches for - * specific URLs. - * - * @example - *
-   * var app = angular.module('app', ['ui.router.router']);
-   *
-   * app.config(function ($urlRouterProvider) {
-   *   // Here's an example of how you might allow case insensitive urls
-   *   $urlRouterProvider.rule(function ($injector, $location) {
-   *     var path = $location.path(),
-   *         normalized = path.toLowerCase();
-   *
-   *     if (path !== normalized) {
-   *       return normalized;
-   *     }
-   *   });
-   * });
-   * 
- * - * @param {function} rule Handler function that takes `$injector` and `$location` - * services as arguments. You can use them to return a valid path as a string. - * - * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance - */ - this.rule = function (rule) { - if (!isFunction(rule)) throw new Error("'rule' must be a function"); - rules.push(rule); - return this; - }; - - /** - * @ngdoc object - * @name ui.router.router.$urlRouterProvider#otherwise - * @methodOf ui.router.router.$urlRouterProvider - * - * @description - * Defines a path that is used when an invalid route is requested. - * - * @example - *
-   * var app = angular.module('app', ['ui.router.router']);
-   *
-   * app.config(function ($urlRouterProvider) {
-   *   // if the path doesn't match any of the urls you configured
-   *   // otherwise will take care of routing the user to the
-   *   // specified url
-   *   $urlRouterProvider.otherwise('/index');
-   *
-   *   // Example of using function rule as param
-   *   $urlRouterProvider.otherwise(function ($injector, $location) {
-   *     return '/a/valid/url';
-   *   });
-   * });
-   * 
- * - * @param {string|function} rule The url path you want to redirect to or a function - * rule that returns the url path. The function version is passed two params: - * `$injector` and `$location` services, and must return a url string. - * - * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance - */ - this.otherwise = function (rule) { - if (isString(rule)) { - var redirect = rule; - rule = function () { return redirect; }; - } - else if (!isFunction(rule)) throw new Error("'rule' must be a function"); - otherwise = rule; - return this; - }; - - - function handleIfMatch($injector, handler, match) { - if (!match) return false; - var result = $injector.invoke(handler, handler, { $match: match }); - return isDefined(result) ? result : true; - } - - /** - * @ngdoc function - * @name ui.router.router.$urlRouterProvider#when - * @methodOf ui.router.router.$urlRouterProvider - * - * @description - * Registers a handler for a given url matching. - * - * If the handler is a string, it is - * treated as a redirect, and is interpolated according to the syntax of match - * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise). - * - * If the handler is a function, it is injectable. It gets invoked if `$location` - * matches. You have the option of inject the match object as `$match`. - * - * The handler can return - * - * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter` - * will continue trying to find another one that matches. - * - **string** which is treated as a redirect and passed to `$location.url()` - * - **void** or any **truthy** value tells `$urlRouter` that the url was handled. - * - * @example - *
-   * var app = angular.module('app', ['ui.router.router']);
-   *
-   * app.config(function ($urlRouterProvider) {
-   *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
-   *     if ($state.$current.navigable !== state ||
-   *         !equalForKeys($match, $stateParams) {
-   *      $state.transitionTo(state, $match, false);
-   *     }
-   *   });
-   * });
-   * 
- * - * @param {string|object} what The incoming path that you want to redirect. - * @param {string|function} handler The path you want to redirect your user to. - */ - this.when = function (what, handler) { - var redirect, handlerIsString = isString(handler); - if (isString(what)) what = $urlMatcherFactory.compile(what); - - if (!handlerIsString && !isFunction(handler) && !isArray(handler)) - throw new Error("invalid 'handler' in when()"); - - var strategies = { - matcher: function (what, handler) { - if (handlerIsString) { - redirect = $urlMatcherFactory.compile(handler); - handler = ['$match', function ($match) { return redirect.format($match); }]; - } - return extend(function ($injector, $location) { - return handleIfMatch($injector, handler, what.exec($location.path(), $location.search())); - }, { - prefix: isString(what.prefix) ? what.prefix : '' - }); - }, - regex: function (what, handler) { - if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky"); - - if (handlerIsString) { - redirect = handler; - handler = ['$match', function ($match) { return interpolate(redirect, $match); }]; - } - return extend(function ($injector, $location) { - return handleIfMatch($injector, handler, what.exec($location.path())); - }, { - prefix: regExpPrefix(what) - }); - } - }; - - var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp }; - - for (var n in check) { - if (check[n]) return this.rule(strategies[n](what, handler)); - } - - throw new Error("invalid 'what' in when()"); - }; - - /** - * @ngdoc function - * @name ui.router.router.$urlRouterProvider#deferIntercept - * @methodOf ui.router.router.$urlRouterProvider - * - * @description - * Disables (or enables) deferring location change interception. - * - * If you wish to customize the behavior of syncing the URL (for example, if you wish to - * defer a transition but maintain the current URL), call this method at configuration time. - * Then, at run time, call `$urlRouter.listen()` after you have configured your own - * `$locationChangeSuccess` event handler. - * - * @example - *
-   * var app = angular.module('app', ['ui.router.router']);
-   *
-   * app.config(function ($urlRouterProvider) {
-   *
-   *   // Prevent $urlRouter from automatically intercepting URL changes;
-   *   // this allows you to configure custom behavior in between
-   *   // location changes and route synchronization:
-   *   $urlRouterProvider.deferIntercept();
-   *
-   * }).run(function ($rootScope, $urlRouter, UserService) {
-   *
-   *   $rootScope.$on('$locationChangeSuccess', function(e) {
-   *     // UserService is an example service for managing user state
-   *     if (UserService.isLoggedIn()) return;
-   *
-   *     // Prevent $urlRouter's default handler from firing
-   *     e.preventDefault();
-   *
-   *     UserService.handleLogin().then(function() {
-   *       // Once the user has logged in, sync the current URL
-   *       // to the router:
-   *       $urlRouter.sync();
-   *     });
-   *   });
-   *
-   *   // Configures $urlRouter's listener *after* your custom listener
-   *   $urlRouter.listen();
-   * });
-   * 
- * - * @param {boolean} defer Indicates whether to defer location change interception. Passing - no parameter is equivalent to `true`. - */ - this.deferIntercept = function (defer) { - if (defer === undefined) defer = true; - interceptDeferred = defer; - }; - - /** - * @ngdoc object - * @name ui.router.router.$urlRouter - * - * @requires $location - * @requires $rootScope - * @requires $injector - * @requires $browser - * - * @description - * - */ - this.$get = $get; - $get.$inject = ['$location', '$rootScope', '$injector', '$browser', '$sniffer']; - function $get( $location, $rootScope, $injector, $browser, $sniffer) { - - var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl; - - function appendBasePath(url, isHtml5, absolute) { - if (baseHref === '/') return url; - if (isHtml5) return baseHref.slice(0, -1) + url; - if (absolute) return baseHref.slice(1) + url; - return url; - } - - // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree - function update(evt) { - if (evt && evt.defaultPrevented) return; - var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl; - lastPushedUrl = undefined; - // TODO: Re-implement this in 1.0 for https://github.com/angular-ui/ui-router/issues/1573 - //if (ignoreUpdate) return true; - - function check(rule) { - var handled = rule($injector, $location); - - if (!handled) return false; - if (isString(handled)) $location.replace().url(handled); - return true; - } - var n = rules.length, i; - - for (i = 0; i < n; i++) { - if (check(rules[i])) return; - } - // always check otherwise last to allow dynamic updates to the set of rules - if (otherwise) check(otherwise); - } - - function listen() { - listener = listener || $rootScope.$on('$locationChangeSuccess', update); - return listener; - } - - if (!interceptDeferred) listen(); - - return { - /** - * @ngdoc function - * @name ui.router.router.$urlRouter#sync - * @methodOf ui.router.router.$urlRouter - * - * @description - * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`. - * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event, - * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed - * with the transition by calling `$urlRouter.sync()`. - * - * @example - *
-       * angular.module('app', ['ui.router'])
-       *   .run(function($rootScope, $urlRouter) {
-       *     $rootScope.$on('$locationChangeSuccess', function(evt) {
-       *       // Halt state change from even starting
-       *       evt.preventDefault();
-       *       // Perform custom logic
-       *       var meetsRequirement = ...
-       *       // Continue with the update and state transition if logic allows
-       *       if (meetsRequirement) $urlRouter.sync();
-       *     });
-       * });
-       * 
- */ - sync: function() { - update(); - }, - - listen: function() { - return listen(); - }, - - update: function(read) { - if (read) { - location = $location.url(); - return; - } - if ($location.url() === location) return; - - $location.url(location); - $location.replace(); - }, - - push: function(urlMatcher, params, options) { - var url = urlMatcher.format(params || {}); - - // Handle the special hash param, if needed - if (url !== null && params && params['#']) { - url += '#' + params['#']; - } - - $location.url(url); - lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined; - if (options && options.replace) $location.replace(); - }, - - /** - * @ngdoc function - * @name ui.router.router.$urlRouter#href - * @methodOf ui.router.router.$urlRouter - * - * @description - * A URL generation method that returns the compiled URL for a given - * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters. - * - * @example - *
-       * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
-       *   person: "bob"
-       * });
-       * // $bob == "/about/bob";
-       * 
- * - * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate. - * @param {object=} params An object of parameter values to fill the matcher's required parameters. - * @param {object=} options Options object. The options are: - * - * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". - * - * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher` - */ - href: function(urlMatcher, params, options) { - if (!urlMatcher.validates(params)) return null; - - var isHtml5 = $locationProvider.html5Mode(); - if (angular.isObject(isHtml5)) { - isHtml5 = isHtml5.enabled; - } - - isHtml5 = isHtml5 && $sniffer.history; - - var url = urlMatcher.format(params); - options = options || {}; - - if (!isHtml5 && url !== null) { - url = "#" + $locationProvider.hashPrefix() + url; - } - - // Handle special hash param, if needed - if (url !== null && params && params['#']) { - url += '#' + params['#']; - } - - url = appendBasePath(url, isHtml5, options.absolute); - - if (!options.absolute || !url) { - return url; - } - - var slash = (!isHtml5 && url ? '/' : ''), port = $location.port(); - port = (port === 80 || port === 443 ? '' : ':' + port); - - return [$location.protocol(), '://', $location.host(), port, slash, url].join(''); - } - }; - } -} - -angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider); - -/** - * @ngdoc object - * @name ui.router.state.$stateProvider - * - * @requires ui.router.router.$urlRouterProvider - * @requires ui.router.util.$urlMatcherFactoryProvider - * - * @description - * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely - * on state. - * - * A state corresponds to a "place" in the application in terms of the overall UI and - * navigation. A state describes (via the controller / template / view properties) what - * the UI looks like and does at that place. - * - * States often have things in common, and the primary way of factoring out these - * commonalities in this model is via the state hierarchy, i.e. parent/child states aka - * nested states. - * - * The `$stateProvider` provides interfaces to declare these states for your app. - */ -$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider']; -function $StateProvider( $urlRouterProvider, $urlMatcherFactory) { - - var root, states = {}, $state, queue = {}, abstractKey = 'abstract'; - - // Builds state properties from definition passed to registerState() - var stateBuilder = { - - // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined. - // state.children = []; - // if (parent) parent.children.push(state); - parent: function(state) { - if (isDefined(state.parent) && state.parent) return findState(state.parent); - // regex matches any valid composite state name - // would match "contact.list" but not "contacts" - var compositeName = /^(.+)\.[^.]+$/.exec(state.name); - return compositeName ? findState(compositeName[1]) : root; - }, - - // inherit 'data' from parent and override by own values (if any) - data: function(state) { - if (state.parent && state.parent.data) { - state.data = state.self.data = inherit(state.parent.data, state.data); - } - return state.data; - }, - - // Build a URLMatcher if necessary, either via a relative or absolute URL - url: function(state) { - var url = state.url, config = { params: state.params || {} }; - - if (isString(url)) { - if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config); - return (state.parent.navigable || root).url.concat(url, config); - } - - if (!url || $urlMatcherFactory.isMatcher(url)) return url; - throw new Error("Invalid url '" + url + "' in state '" + state + "'"); - }, - - // Keep track of the closest ancestor state that has a URL (i.e. is navigable) - navigable: function(state) { - return state.url ? state : (state.parent ? state.parent.navigable : null); - }, - - // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params - ownParams: function(state) { - var params = state.url && state.url.params || new $$UMFP.ParamSet(); - forEach(state.params || {}, function(config, id) { - if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config"); - }); - return params; - }, - - // Derive parameters for this state and ensure they're a super-set of parent's parameters - params: function(state) { - var ownParams = pick(state.ownParams, state.ownParams.$$keys()); - return state.parent && state.parent.params ? extend(state.parent.params.$$new(), ownParams) : new $$UMFP.ParamSet(); - }, - - // If there is no explicit multi-view configuration, make one up so we don't have - // to handle both cases in the view directive later. Note that having an explicit - // 'views' property will mean the default unnamed view properties are ignored. This - // is also a good time to resolve view names to absolute names, so everything is a - // straight lookup at link time. - views: function(state) { - var views = {}; - - forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) { - if (name.indexOf('@') < 0) name += '@' + state.parent.name; - views[name] = view; - }); - return views; - }, - - // Keep a full path from the root down to this state as this is needed for state activation. - path: function(state) { - return state.parent ? state.parent.path.concat(state) : []; // exclude root from path - }, - - // Speed up $state.contains() as it's used a lot - includes: function(state) { - var includes = state.parent ? extend({}, state.parent.includes) : {}; - includes[state.name] = true; - return includes; - }, - - $delegates: {} - }; - - function isRelative(stateName) { - return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0; - } - - function findState(stateOrName, base) { - if (!stateOrName) return undefined; - - var isStr = isString(stateOrName), - name = isStr ? stateOrName : stateOrName.name, - path = isRelative(name); - - if (path) { - if (!base) throw new Error("No reference point given for path '" + name + "'"); - base = findState(base); - - var rel = name.split("."), i = 0, pathLength = rel.length, current = base; - - for (; i < pathLength; i++) { - if (rel[i] === "" && i === 0) { - current = base; - continue; - } - if (rel[i] === "^") { - if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'"); - current = current.parent; - continue; - } - break; - } - rel = rel.slice(i).join("."); - name = current.name + (current.name && rel ? "." : "") + rel; - } - var state = states[name]; - - if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) { - return state; - } - return undefined; - } - - function queueState(parentName, state) { - if (!queue[parentName]) { - queue[parentName] = []; - } - queue[parentName].push(state); - } - - function flushQueuedChildren(parentName) { - var queued = queue[parentName] || []; - while(queued.length) { - registerState(queued.shift()); - } - } - - function registerState(state) { - // Wrap a new object around the state so we can store our private details easily. - state = inherit(state, { - self: state, - resolve: state.resolve || {}, - toString: function() { return this.name; } - }); - - var name = state.name; - if (!isString(name) || name.indexOf('@') >= 0) throw new Error("State must have a valid name"); - if (states.hasOwnProperty(name)) throw new Error("State '" + name + "' is already defined"); - - // Get parent name - var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.')) - : (isString(state.parent)) ? state.parent - : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name - : ''; - - // If parent is not registered yet, add state to queue and register later - if (parentName && !states[parentName]) { - return queueState(parentName, state.self); - } - - for (var key in stateBuilder) { - if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]); - } - states[name] = state; - - // Register the state in the global state list and with $urlRouter if necessary. - if (!state[abstractKey] && state.url) { - $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) { - if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) { - $state.transitionTo(state, $match, { inherit: true, location: false }); - } - }]); - } - - // Register any queued children - flushQueuedChildren(name); - - return state; - } - - // Checks text to see if it looks like a glob. - function isGlob (text) { - return text.indexOf('*') > -1; - } - - // Returns true if glob matches current $state name. - function doesStateMatchGlob (glob) { - var globSegments = glob.split('.'), - segments = $state.$current.name.split('.'); - - //match single stars - for (var i = 0, l = globSegments.length; i < l; i++) { - if (globSegments[i] === '*') { - segments[i] = '*'; - } - } - - //match greedy starts - if (globSegments[0] === '**') { - segments = segments.slice(indexOf(segments, globSegments[1])); - segments.unshift('**'); - } - //match greedy ends - if (globSegments[globSegments.length - 1] === '**') { - segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE); - segments.push('**'); - } - - if (globSegments.length != segments.length) { - return false; - } - - return segments.join('') === globSegments.join(''); - } - - - // Implicit root state that is always active - root = registerState({ - name: '', - url: '^', - views: null, - 'abstract': true - }); - root.navigable = null; - - - /** - * @ngdoc function - * @name ui.router.state.$stateProvider#decorator - * @methodOf ui.router.state.$stateProvider - * - * @description - * Allows you to extend (carefully) or override (at your own peril) the - * `stateBuilder` object used internally by `$stateProvider`. This can be used - * to add custom functionality to ui-router, for example inferring templateUrl - * based on the state name. - * - * When passing only a name, it returns the current (original or decorated) builder - * function that matches `name`. - * - * The builder functions that can be decorated are listed below. Though not all - * necessarily have a good use case for decoration, that is up to you to decide. - * - * In addition, users can attach custom decorators, which will generate new - * properties within the state's internal definition. There is currently no clear - * use-case for this beyond accessing internal states (i.e. $state.$current), - * however, expect this to become increasingly relevant as we introduce additional - * meta-programming features. - * - * **Warning**: Decorators should not be interdependent because the order of - * execution of the builder functions in non-deterministic. Builder functions - * should only be dependent on the state definition object and super function. - * - * - * Existing builder functions and current return values: - * - * - **parent** `{object}` - returns the parent state object. - * - **data** `{object}` - returns state data, including any inherited data that is not - * overridden by own values (if any). - * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher} - * or `null`. - * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is - * navigable). - * - **params** `{object}` - returns an array of state params that are ensured to - * be a super-set of parent's params. - * - **views** `{object}` - returns a views object where each key is an absolute view - * name (i.e. "viewName@stateName") and each value is the config object - * (template, controller) for the view. Even when you don't use the views object - * explicitly on a state config, one is still created for you internally. - * So by decorating this builder function you have access to decorating template - * and controller properties. - * - **ownParams** `{object}` - returns an array of params that belong to the state, - * not including any params defined by ancestor states. - * - **path** `{string}` - returns the full path from the root down to this state. - * Needed for state activation. - * - **includes** `{object}` - returns an object that includes every state that - * would pass a `$state.includes()` test. - * - * @example - *
-   * // Override the internal 'views' builder with a function that takes the state
-   * // definition, and a reference to the internal function being overridden:
-   * $stateProvider.decorator('views', function (state, parent) {
-   *   var result = {},
-   *       views = parent(state);
-   *
-   *   angular.forEach(views, function (config, name) {
-   *     var autoName = (state.name + '.' + name).replace('.', '/');
-   *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
-   *     result[name] = config;
-   *   });
-   *   return result;
-   * });
-   *
-   * $stateProvider.state('home', {
-   *   views: {
-   *     'contact.list': { controller: 'ListController' },
-   *     'contact.item': { controller: 'ItemController' }
-   *   }
-   * });
-   *
-   * // ...
-   *
-   * $state.go('home');
-   * // Auto-populates list and item views with /partials/home/contact/list.html,
-   * // and /partials/home/contact/item.html, respectively.
-   * 
- * - * @param {string} name The name of the builder function to decorate. - * @param {object} func A function that is responsible for decorating the original - * builder function. The function receives two parameters: - * - * - `{object}` - state - The state config object. - * - `{object}` - super - The original builder function. - * - * @return {object} $stateProvider - $stateProvider instance - */ - this.decorator = decorator; - function decorator(name, func) { - /*jshint validthis: true */ - if (isString(name) && !isDefined(func)) { - return stateBuilder[name]; - } - if (!isFunction(func) || !isString(name)) { - return this; - } - if (stateBuilder[name] && !stateBuilder.$delegates[name]) { - stateBuilder.$delegates[name] = stateBuilder[name]; - } - stateBuilder[name] = func; - return this; - } - - /** - * @ngdoc function - * @name ui.router.state.$stateProvider#state - * @methodOf ui.router.state.$stateProvider - * - * @description - * Registers a state configuration under a given state name. The stateConfig object - * has the following acceptable properties. - * - * @param {string} name A unique state name, e.g. "home", "about", "contacts". - * To create a parent/child state use a dot, e.g. "about.sales", "home.newest". - * @param {object} stateConfig State configuration object. - * @param {string|function=} stateConfig.template - * - * html template as a string or a function that returns - * an html template as a string which should be used by the uiView directives. This property - * takes precedence over templateUrl. - * - * If `template` is a function, it will be called with the following parameters: - * - * - {array.<object>} - state parameters extracted from the current $location.path() by - * applying the current state - * - *
template:
-   *   "

inline template definition

" + - * "
"
- *
template: function(params) {
-   *       return "

generated template

"; }
- * - * - * @param {string|function=} stateConfig.templateUrl - * - * - * path or function that returns a path to an html - * template that should be used by uiView. - * - * If `templateUrl` is a function, it will be called with the following parameters: - * - * - {array.<object>} - state parameters extracted from the current $location.path() by - * applying the current state - * - *
templateUrl: "home.html"
- *
templateUrl: function(params) {
-   *     return myTemplates[params.pageId]; }
- * - * @param {function=} stateConfig.templateProvider - * - * Provider function that returns HTML content string. - *
 templateProvider:
-   *       function(MyTemplateService, params) {
-   *         return MyTemplateService.getTemplate(params.pageId);
-   *       }
- * - * @param {string|function=} stateConfig.controller - * - * - * Controller fn that should be associated with newly - * related scope or the name of a registered controller if passed as a string. - * Optionally, the ControllerAs may be declared here. - *
controller: "MyRegisteredController"
- *
controller:
-   *     "MyRegisteredController as fooCtrl"}
- *
controller: function($scope, MyService) {
-   *     $scope.data = MyService.getData(); }
- * - * @param {function=} stateConfig.controllerProvider - * - * - * Injectable provider function that returns the actual controller or string. - *
controllerProvider:
-   *   function(MyResolveData) {
-   *     if (MyResolveData.foo)
-   *       return "FooCtrl"
-   *     else if (MyResolveData.bar)
-   *       return "BarCtrl";
-   *     else return function($scope) {
-   *       $scope.baz = "Qux";
-   *     }
-   *   }
- * - * @param {string=} stateConfig.controllerAs - * - * - * A controller alias name. If present the controller will be - * published to scope under the controllerAs name. - *
controllerAs: "myCtrl"
- * - * @param {string|object=} stateConfig.parent - * - * Optionally specifies the parent state of this state. - * - *
parent: 'parentState'
- *
parent: parentState // JS variable
- * - * @param {object=} stateConfig.resolve - * - * - * An optional map<string, function> of dependencies which - * should be injected into the controller. If any of these dependencies are promises, - * the router will wait for them all to be resolved before the controller is instantiated. - * If all the promises are resolved successfully, the $stateChangeSuccess event is fired - * and the values of the resolved promises are injected into any controllers that reference them. - * If any of the promises are rejected the $stateChangeError event is fired. - * - * The map object is: - * - * - key - {string}: name of dependency to be injected into controller - * - factory - {string|function}: If string then it is alias for service. Otherwise if function, - * it is injected and return value it treated as dependency. If result is a promise, it is - * resolved before its value is injected into controller. - * - *
resolve: {
-   *     myResolve1:
-   *       function($http, $stateParams) {
-   *         return $http.get("/api/foos/"+stateParams.fooID);
-   *       }
-   *     }
- * - * @param {string=} stateConfig.url - * - * - * A url fragment with optional parameters. When a state is navigated or - * transitioned to, the `$stateParams` service will be populated with any - * parameters that were passed. - * - * (See {@link ui.router.util.type:UrlMatcher UrlMatcher} `UrlMatcher`} for - * more details on acceptable patterns ) - * - * examples: - *
url: "/home"
-   * url: "/users/:userid"
-   * url: "/books/{bookid:[a-zA-Z_-]}"
-   * url: "/books/{categoryid:int}"
-   * url: "/books/{publishername:string}/{categoryid:int}"
-   * url: "/messages?before&after"
-   * url: "/messages?{before:date}&{after:date}"
-   * url: "/messages/:mailboxid?{before:date}&{after:date}"
-   * 
- * - * @param {object=} stateConfig.views - * - * an optional map<string, object> which defined multiple views, or targets views - * manually/explicitly. - * - * Examples: - * - * Targets three named `ui-view`s in the parent state's template - *
views: {
-   *     header: {
-   *       controller: "headerCtrl",
-   *       templateUrl: "header.html"
-   *     }, body: {
-   *       controller: "bodyCtrl",
-   *       templateUrl: "body.html"
-   *     }, footer: {
-   *       controller: "footCtrl",
-   *       templateUrl: "footer.html"
-   *     }
-   *   }
- * - * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template. - *
views: {
-   *     'header@top': {
-   *       controller: "msgHeaderCtrl",
-   *       templateUrl: "msgHeader.html"
-   *     }, 'body': {
-   *       controller: "messagesCtrl",
-   *       templateUrl: "messages.html"
-   *     }
-   *   }
- * - * @param {boolean=} [stateConfig.abstract=false] - * - * An abstract state will never be directly activated, - * but can provide inherited properties to its common children states. - *
abstract: true
- * - * @param {function=} stateConfig.onEnter - * - * - * Callback function for when a state is entered. Good way - * to trigger an action or dispatch an event, such as opening a dialog. - * If minifying your scripts, make sure to explicitly annotate this function, - * because it won't be automatically annotated by your build tools. - * - *
onEnter: function(MyService, $stateParams) {
-   *     MyService.foo($stateParams.myParam);
-   * }
- * - * @param {function=} stateConfig.onExit - * - * - * Callback function for when a state is exited. Good way to - * trigger an action or dispatch an event, such as opening a dialog. - * If minifying your scripts, make sure to explicitly annotate this function, - * because it won't be automatically annotated by your build tools. - * - *
onExit: function(MyService, $stateParams) {
-   *     MyService.cleanup($stateParams.myParam);
-   * }
- * - * @param {boolean=} [stateConfig.reloadOnSearch=true] - * - * - * If `false`, will not retrigger the same state - * just because a search/query parameter has changed (via $location.search() or $location.hash()). - * Useful for when you'd like to modify $location.search() without triggering a reload. - *
reloadOnSearch: false
- * - * @param {object=} stateConfig.data - * - * - * Arbitrary data object, useful for custom configuration. The parent state's `data` is - * prototypally inherited. In other words, adding a data property to a state adds it to - * the entire subtree via prototypal inheritance. - * - *
data: {
-   *     requiredRole: 'foo'
-   * } 
- * - * @param {object=} stateConfig.params - * - * - * A map which optionally configures parameters declared in the `url`, or - * defines additional non-url parameters. For each parameter being - * configured, add a configuration object keyed to the name of the parameter. - * - * Each parameter configuration object may contain the following properties: - * - * - ** value ** - {object|function=}: specifies the default value for this - * parameter. This implicitly sets this parameter as optional. - * - * When UI-Router routes to a state and no value is - * specified for this parameter in the URL or transition, the - * default value will be used instead. If `value` is a function, - * it will be injected and invoked, and the return value used. - * - * *Note*: `undefined` is treated as "no default value" while `null` - * is treated as "the default value is `null`". - * - * *Shorthand*: If you only need to configure the default value of the - * parameter, you may use a shorthand syntax. In the **`params`** - * map, instead mapping the param name to a full parameter configuration - * object, simply set map it to the default parameter value, e.g.: - * - *
// define a parameter's default value
-   * params: {
-   *     param1: { value: "defaultValue" }
-   * }
-   * // shorthand default values
-   * params: {
-   *     param1: "defaultValue",
-   *     param2: "param2Default"
-   * }
- * - * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be - * treated as an array of values. If you specified a Type, the value will be - * treated as an array of the specified Type. Note: query parameter values - * default to a special `"auto"` mode. - * - * For query parameters in `"auto"` mode, if multiple values for a single parameter - * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values - * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if - * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single - * value (e.g.: `{ foo: '1' }`). - * - *
params: {
-   *     param1: { array: true }
-   * }
- * - * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when - * the current parameter value is the same as the default value. If `squash` is not set, it uses the - * configured default squash policy. - * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`}) - * - * There are three squash settings: - * - * - false: The parameter's default value is not squashed. It is encoded and included in the URL - * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed - * by slashes in the state's `url` declaration, then one of those slashes are omitted. - * This can allow for cleaner looking URLs. - * - `""`: The parameter's default value is replaced with an arbitrary placeholder of your choice. - * - *
params: {
-   *     param1: {
-   *       value: "defaultId",
-   *       squash: true
-   * } }
-   * // squash "defaultValue" to "~"
-   * params: {
-   *     param1: {
-   *       value: "defaultValue",
-   *       squash: "~"
-   * } }
-   * 
- * - * - * @example - *
-   * // Some state name examples
-   *
-   * // stateName can be a single top-level name (must be unique).
-   * $stateProvider.state("home", {});
-   *
-   * // Or it can be a nested state name. This state is a child of the
-   * // above "home" state.
-   * $stateProvider.state("home.newest", {});
-   *
-   * // Nest states as deeply as needed.
-   * $stateProvider.state("home.newest.abc.xyz.inception", {});
-   *
-   * // state() returns $stateProvider, so you can chain state declarations.
-   * $stateProvider
-   *   .state("home", {})
-   *   .state("about", {})
-   *   .state("contacts", {});
-   * 
- * - */ - this.state = state; - function state(name, definition) { - /*jshint validthis: true */ - if (isObject(name)) definition = name; - else definition.name = name; - registerState(definition); - return this; - } - - /** - * @ngdoc object - * @name ui.router.state.$state - * - * @requires $rootScope - * @requires $q - * @requires ui.router.state.$view - * @requires $injector - * @requires ui.router.util.$resolve - * @requires ui.router.state.$stateParams - * @requires ui.router.router.$urlRouter - * - * @property {object} params A param object, e.g. {sectionId: section.id)}, that - * you'd like to test against the current active state. - * @property {object} current A reference to the state's config object. However - * you passed it in. Useful for accessing custom data. - * @property {object} transition Currently pending transition. A promise that'll - * resolve or reject. - * - * @description - * `$state` service is responsible for representing states as well as transitioning - * between them. It also provides interfaces to ask for current state or even states - * you're coming from. - */ - this.$get = $get; - $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory']; - function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) { - - var TransitionSuperseded = $q.reject(new Error('transition superseded')); - var TransitionPrevented = $q.reject(new Error('transition prevented')); - var TransitionAborted = $q.reject(new Error('transition aborted')); - var TransitionFailed = $q.reject(new Error('transition failed')); - - // Handles the case where a state which is the target of a transition is not found, and the user - // can optionally retry or defer the transition - function handleRedirect(redirect, state, params, options) { - /** - * @ngdoc event - * @name ui.router.state.$state#$stateNotFound - * @eventOf ui.router.state.$state - * @eventType broadcast on root scope - * @description - * Fired when a requested state **cannot be found** using the provided state name during transition. - * The event is broadcast allowing any handlers a single chance to deal with the error (usually by - * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler, - * you can see its three properties in the example. You can use `event.preventDefault()` to abort the - * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value. - * - * @param {Object} event Event object. - * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties. - * @param {State} fromState Current state object. - * @param {Object} fromParams Current state params. - * - * @example - * - *
-       * // somewhere, assume lazy.state has not been defined
-       * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
-       *
-       * // somewhere else
-       * $scope.$on('$stateNotFound',
-       * function(event, unfoundState, fromState, fromParams){
-       *     console.log(unfoundState.to); // "lazy.state"
-       *     console.log(unfoundState.toParams); // {a:1, b:2}
-       *     console.log(unfoundState.options); // {inherit:false} + default options
-       * })
-       * 
- */ - var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params); - - if (evt.defaultPrevented) { - $urlRouter.update(); - return TransitionAborted; - } - - if (!evt.retry) { - return null; - } - - // Allow the handler to return a promise to defer state lookup retry - if (options.$retry) { - $urlRouter.update(); - return TransitionFailed; - } - var retryTransition = $state.transition = $q.when(evt.retry); - - retryTransition.then(function() { - if (retryTransition !== $state.transition) return TransitionSuperseded; - redirect.options.$retry = true; - return $state.transitionTo(redirect.to, redirect.toParams, redirect.options); - }, function() { - return TransitionAborted; - }); - $urlRouter.update(); - - return retryTransition; - } - - root.locals = { resolve: null, globals: { $stateParams: {} } }; - - $state = { - params: {}, - current: root.self, - $current: root, - transition: null - }; - - /** - * @ngdoc function - * @name ui.router.state.$state#reload - * @methodOf ui.router.state.$state - * - * @description - * A method that force reloads the current state. All resolves are re-resolved, - * controllers reinstantiated, and events re-fired. - * - * @example - *
-     * var app angular.module('app', ['ui.router']);
-     *
-     * app.controller('ctrl', function ($scope, $state) {
-     *   $scope.reload = function(){
-     *     $state.reload();
-     *   }
-     * });
-     * 
- * - * `reload()` is just an alias for: - *
-     * $state.transitionTo($state.current, $stateParams, { 
-     *   reload: true, inherit: false, notify: true
-     * });
-     * 
- * - * @param {string=|object=} state - A state name or a state object, which is the root of the resolves to be re-resolved. - * @example - *
-     * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item' 
-     * //and current state is 'contacts.detail.item'
-     * var app angular.module('app', ['ui.router']);
-     *
-     * app.controller('ctrl', function ($scope, $state) {
-     *   $scope.reload = function(){
-     *     //will reload 'contact.detail' and 'contact.detail.item' states
-     *     $state.reload('contact.detail');
-     *   }
-     * });
-     * 
- * - * `reload()` is just an alias for: - *
-     * $state.transitionTo($state.current, $stateParams, { 
-     *   reload: true, inherit: false, notify: true
-     * });
-     * 
- - * @returns {promise} A promise representing the state of the new transition. See - * {@link ui.router.state.$state#methods_go $state.go}. - */ - $state.reload = function reload(state) { - return $state.transitionTo($state.current, $stateParams, { reload: state || true, inherit: false, notify: true}); - }; - - /** - * @ngdoc function - * @name ui.router.state.$state#go - * @methodOf ui.router.state.$state - * - * @description - * Convenience method for transitioning to a new state. `$state.go` calls - * `$state.transitionTo` internally but automatically sets options to - * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. - * This allows you to easily use an absolute or relative to path and specify - * only the parameters you'd like to update (while letting unspecified parameters - * inherit from the currently active ancestor states). - * - * @example - *
-     * var app = angular.module('app', ['ui.router']);
-     *
-     * app.controller('ctrl', function ($scope, $state) {
-     *   $scope.changeState = function () {
-     *     $state.go('contact.detail');
-     *   };
-     * });
-     * 
- * - * - * @param {string} to Absolute state name or relative state path. Some examples: - * - * - `$state.go('contact.detail')` - will go to the `contact.detail` state - * - `$state.go('^')` - will go to a parent state - * - `$state.go('^.sibling')` - will go to a sibling state - * - `$state.go('.child.grandchild')` - will go to grandchild state - * - * @param {object=} params A map of the parameters that will be sent to the state, - * will populate $stateParams. Any parameters that are not specified will be inherited from currently - * defined parameters. Only parameters specified in the state definition can be overridden, new - * parameters will be ignored. This allows, for example, going to a sibling state that shares parameters - * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e. - * transitioning to a sibling will get you the parameters for all parents, transitioning to a child - * will get you all current parameters, etc. - * @param {object=} options Options object. The options are: - * - * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` - * will not. If string, must be `"replace"`, which will update url and also replace last history record. - * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. - * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), - * defines which state to be relative from. - * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. - * - **`reload`** (v0.2.5) - {boolean=false|string|object}, If `true` will force transition even if no state or params - * have changed. It will reload the resolves and views of the current state and parent states. - * If `reload` is a string (or state object), the state object is fetched (by name, or object reference); and \ - * the transition reloads the resolves and views for that matched state, and all its children states. - * - * @returns {promise} A promise representing the state of the new transition. - * - * Possible success values: - * - * - $state.current - * - *
Possible rejection values: - * - * - 'transition superseded' - when a newer transition has been started after this one - * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener - * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or - * when a `$stateNotFound` `event.retry` promise errors. - * - 'transition failed' - when a state has been unsuccessfully found after 2 tries. - * - *resolve error* - when an error has occurred with a `resolve` - * - */ - $state.go = function go(to, params, options) { - return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options)); - }; - - /** - * @ngdoc function - * @name ui.router.state.$state#transitionTo - * @methodOf ui.router.state.$state - * - * @description - * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go} - * uses `transitionTo` internally. `$state.go` is recommended in most situations. - * - * @example - *
-     * var app = angular.module('app', ['ui.router']);
-     *
-     * app.controller('ctrl', function ($scope, $state) {
-     *   $scope.changeState = function () {
-     *     $state.transitionTo('contact.detail');
-     *   };
-     * });
-     * 
- * - * @param {string} to State name. - * @param {object=} toParams A map of the parameters that will be sent to the state, - * will populate $stateParams. - * @param {object=} options Options object. The options are: - * - * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` - * will not. If string, must be `"replace"`, which will update url and also replace last history record. - * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url. - * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), - * defines which state to be relative from. - * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. - * - **`reload`** (v0.2.5) - {boolean=false|string=|object=}, If `true` will force transition even if the state or params - * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd - * use this when you want to force a reload when *everything* is the same, including search params. - * if String, then will reload the state with the name given in reload, and any children. - * if Object, then a stateObj is expected, will reload the state found in stateObj, and any children. - * - * @returns {promise} A promise representing the state of the new transition. See - * {@link ui.router.state.$state#methods_go $state.go}. - */ - $state.transitionTo = function transitionTo(to, toParams, options) { - toParams = toParams || {}; - options = extend({ - location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false - }, options || {}); - - var from = $state.$current, fromParams = $state.params, fromPath = from.path; - var evt, toState = findState(to, options.relative); - - // Store the hash param for later (since it will be stripped out by various methods) - var hash = toParams['#']; - - if (!isDefined(toState)) { - var redirect = { to: to, toParams: toParams, options: options }; - var redirectResult = handleRedirect(redirect, from.self, fromParams, options); - - if (redirectResult) { - return redirectResult; - } - - // Always retry once if the $stateNotFound was not prevented - // (handles either redirect changed or state lazy-definition) - to = redirect.to; - toParams = redirect.toParams; - options = redirect.options; - toState = findState(to, options.relative); - - if (!isDefined(toState)) { - if (!options.relative) throw new Error("No such state '" + to + "'"); - throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'"); - } - } - if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'"); - if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState); - if (!toState.params.$$validates(toParams)) return TransitionFailed; - - toParams = toState.params.$$values(toParams); - to = toState; - - var toPath = to.path; - - // Starting from the root of the path, keep all levels that haven't changed - var keep = 0, state = toPath[keep], locals = root.locals, toLocals = []; - - if (!options.reload) { - while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) { - locals = toLocals[keep] = state.locals; - keep++; - state = toPath[keep]; - } - } else if (isString(options.reload) || isObject(options.reload)) { - if (isObject(options.reload) && !options.reload.name) { - throw new Error('Invalid reload state object'); - } - - var reloadState = options.reload === true ? fromPath[0] : findState(options.reload); - if (options.reload && !reloadState) { - throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'"); - } - - while (state && state === fromPath[keep] && state !== reloadState) { - locals = toLocals[keep] = state.locals; - keep++; - state = toPath[keep]; - } - } - - // If we're going to the same state and all locals are kept, we've got nothing to do. - // But clear 'transition', as we still want to cancel any other pending transitions. - // TODO: We may not want to bump 'transition' if we're called from a location change - // that we've initiated ourselves, because we might accidentally abort a legitimate - // transition initiated from code? - if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) { - if (hash) toParams['#'] = hash; - $state.params = toParams; - copy($state.params, $stateParams); - copy(filterByKeys(to.params.$$keys(), $stateParams), to.locals.globals.$stateParams); - if (options.location && to.navigable && to.navigable.url) { - $urlRouter.push(to.navigable.url, toParams, { - $$avoidResync: true, replace: options.location === 'replace' - }); - $urlRouter.update(true); - } - $state.transition = null; - return $q.when($state.current); - } - - // Filter parameters before we pass them to event handlers etc. - toParams = filterByKeys(to.params.$$keys(), toParams || {}); - - // Re-add the saved hash before we start returning things or broadcasting $stateChangeStart - if (hash) toParams['#'] = hash; - - // Broadcast start event and cancel the transition if requested - if (options.notify) { - /** - * @ngdoc event - * @name ui.router.state.$state#$stateChangeStart - * @eventOf ui.router.state.$state - * @eventType broadcast on root scope - * @description - * Fired when the state transition **begins**. You can use `event.preventDefault()` - * to prevent the transition from happening and then the transition promise will be - * rejected with a `'transition prevented'` value. - * - * @param {Object} event Event object. - * @param {State} toState The state being transitioned to. - * @param {Object} toParams The params supplied to the `toState`. - * @param {State} fromState The current state, pre-transition. - * @param {Object} fromParams The params supplied to the `fromState`. - * - * @example - * - *
-         * $rootScope.$on('$stateChangeStart',
-         * function(event, toState, toParams, fromState, fromParams){
-         *     event.preventDefault();
-         *     // transitionTo() promise will be rejected with
-         *     // a 'transition prevented' error
-         * })
-         * 
- */ - if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams, options).defaultPrevented) { - $rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams); - //Don't update and resync url if there's been a new transition started. see issue #2238, #600 - if ($state.transition == null) $urlRouter.update(); - return TransitionPrevented; - } - } - - // Resolve locals for the remaining states, but don't update any global state just - // yet -- if anything fails to resolve the current state needs to remain untouched. - // We also set up an inheritance chain for the locals here. This allows the view directive - // to quickly look up the correct definition for each view in the current state. Even - // though we create the locals object itself outside resolveState(), it is initially - // empty and gets filled asynchronously. We need to keep track of the promise for the - // (fully resolved) current locals, and pass this down the chain. - var resolved = $q.when(locals); - - for (var l = keep; l < toPath.length; l++, state = toPath[l]) { - locals = toLocals[l] = inherit(locals); - resolved = resolveState(state, toParams, state === to, resolved, locals, options); - } - - // Once everything is resolved, we are ready to perform the actual transition - // and return a promise for the new state. We also keep track of what the - // current promise is, so that we can detect overlapping transitions and - // keep only the outcome of the last transition. - var transition = $state.transition = resolved.then(function () { - var l, entering, exiting; - - if ($state.transition !== transition) return TransitionSuperseded; - - // Exit 'from' states not kept - for (l = fromPath.length - 1; l >= keep; l--) { - exiting = fromPath[l]; - if (exiting.self.onExit) { - $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals); - } - exiting.locals = null; - } - - // Enter 'to' states not kept - for (l = keep; l < toPath.length; l++) { - entering = toPath[l]; - entering.locals = toLocals[l]; - if (entering.self.onEnter) { - $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals); - } - } - - // Run it again, to catch any transitions in callbacks - if ($state.transition !== transition) return TransitionSuperseded; - - // Update globals in $state - $state.$current = to; - $state.current = to.self; - $state.params = toParams; - copy($state.params, $stateParams); - $state.transition = null; - - if (options.location && to.navigable) { - $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, { - $$avoidResync: true, replace: options.location === 'replace' - }); - } - - if (options.notify) { - /** - * @ngdoc event - * @name ui.router.state.$state#$stateChangeSuccess - * @eventOf ui.router.state.$state - * @eventType broadcast on root scope - * @description - * Fired once the state transition is **complete**. - * - * @param {Object} event Event object. - * @param {State} toState The state being transitioned to. - * @param {Object} toParams The params supplied to the `toState`. - * @param {State} fromState The current state, pre-transition. - * @param {Object} fromParams The params supplied to the `fromState`. - */ - $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams); - } - $urlRouter.update(true); - - return $state.current; - }, function (error) { - if ($state.transition !== transition) return TransitionSuperseded; - - $state.transition = null; - /** - * @ngdoc event - * @name ui.router.state.$state#$stateChangeError - * @eventOf ui.router.state.$state - * @eventType broadcast on root scope - * @description - * Fired when an **error occurs** during transition. It's important to note that if you - * have any errors in your resolve functions (javascript errors, non-existent services, etc) - * they will not throw traditionally. You must listen for this $stateChangeError event to - * catch **ALL** errors. - * - * @param {Object} event Event object. - * @param {State} toState The state being transitioned to. - * @param {Object} toParams The params supplied to the `toState`. - * @param {State} fromState The current state, pre-transition. - * @param {Object} fromParams The params supplied to the `fromState`. - * @param {Error} error The resolve error object. - */ - evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error); - - if (!evt.defaultPrevented) { - $urlRouter.update(); - } - - return $q.reject(error); - }); - - return transition; - }; - - /** - * @ngdoc function - * @name ui.router.state.$state#is - * @methodOf ui.router.state.$state - * - * @description - * Similar to {@link ui.router.state.$state#methods_includes $state.includes}, - * but only checks for the full state name. If params is supplied then it will be - * tested for strict equality against the current active params object, so all params - * must match with none missing and no extras. - * - * @example - *
-     * $state.$current.name = 'contacts.details.item';
-     *
-     * // absolute name
-     * $state.is('contact.details.item'); // returns true
-     * $state.is(contactDetailItemStateObject); // returns true
-     *
-     * // relative name (. and ^), typically from a template
-     * // E.g. from the 'contacts.details' template
-     * 
Item
- *
- * - * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check. - * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like - * to test against the current active state. - * @param {object=} options An options object. The options are: - * - * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will - * test relative to `options.relative` state (or name). - * - * @returns {boolean} Returns true if it is the state. - */ - $state.is = function is(stateOrName, params, options) { - options = extend({ relative: $state.$current }, options || {}); - var state = findState(stateOrName, options.relative); - - if (!isDefined(state)) { return undefined; } - if ($state.$current !== state) { return false; } - return params ? equalForKeys(state.params.$$values(params), $stateParams) : true; - }; - - /** - * @ngdoc function - * @name ui.router.state.$state#includes - * @methodOf ui.router.state.$state - * - * @description - * A method to determine if the current active state is equal to or is the child of the - * state stateName. If any params are passed then they will be tested for a match as well. - * Not all the parameters need to be passed, just the ones you'd like to test for equality. - * - * @example - * Partial and relative names - *
-     * $state.$current.name = 'contacts.details.item';
-     *
-     * // Using partial names
-     * $state.includes("contacts"); // returns true
-     * $state.includes("contacts.details"); // returns true
-     * $state.includes("contacts.details.item"); // returns true
-     * $state.includes("contacts.list"); // returns false
-     * $state.includes("about"); // returns false
-     *
-     * // Using relative names (. and ^), typically from a template
-     * // E.g. from the 'contacts.details' template
-     * 
Item
- *
- * - * Basic globbing patterns - *
-     * $state.$current.name = 'contacts.details.item.url';
-     *
-     * $state.includes("*.details.*.*"); // returns true
-     * $state.includes("*.details.**"); // returns true
-     * $state.includes("**.item.**"); // returns true
-     * $state.includes("*.details.item.url"); // returns true
-     * $state.includes("*.details.*.url"); // returns true
-     * $state.includes("*.details.*"); // returns false
-     * $state.includes("item.**"); // returns false
-     * 
- * - * @param {string} stateOrName A partial name, relative name, or glob pattern - * to be searched for within the current state name. - * @param {object=} params A param object, e.g. `{sectionId: section.id}`, - * that you'd like to test against the current active state. - * @param {object=} options An options object. The options are: - * - * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set, - * .includes will test relative to `options.relative` state (or name). - * - * @returns {boolean} Returns true if it does include the state - */ - $state.includes = function includes(stateOrName, params, options) { - options = extend({ relative: $state.$current }, options || {}); - if (isString(stateOrName) && isGlob(stateOrName)) { - if (!doesStateMatchGlob(stateOrName)) { - return false; - } - stateOrName = $state.$current.name; - } - - var state = findState(stateOrName, options.relative); - if (!isDefined(state)) { return undefined; } - if (!isDefined($state.$current.includes[state.name])) { return false; } - return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true; - }; - - - /** - * @ngdoc function - * @name ui.router.state.$state#href - * @methodOf ui.router.state.$state - * - * @description - * A url generation method that returns the compiled url for the given state populated with the given params. - * - * @example - *
-     * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
-     * 
- * - * @param {string|object} stateOrName The state name or state object you'd like to generate a url from. - * @param {object=} params An object of parameter values to fill the state's required parameters. - * @param {object=} options Options object. The options are: - * - * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the - * first parameter, then the constructed href url will be built from the first navigable ancestor (aka - * ancestor with a valid url). - * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. - * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), - * defines which state to be relative from. - * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". - * - * @returns {string} compiled state url - */ - $state.href = function href(stateOrName, params, options) { - options = extend({ - lossy: true, - inherit: true, - absolute: false, - relative: $state.$current - }, options || {}); - - var state = findState(stateOrName, options.relative); - - if (!isDefined(state)) return null; - if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state); - - var nav = (state && options.lossy) ? state.navigable : state; - - if (!nav || nav.url === undefined || nav.url === null) { - return null; - } - return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys().concat('#'), params || {}), { - absolute: options.absolute - }); - }; - - /** - * @ngdoc function - * @name ui.router.state.$state#get - * @methodOf ui.router.state.$state - * - * @description - * Returns the state configuration object for any specific state or all states. - * - * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for - * the requested state. If not provided, returns an array of ALL state configs. - * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context. - * @returns {Object|Array} State configuration object or array of all objects. - */ - $state.get = function (stateOrName, context) { - if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; }); - var state = findState(stateOrName, context || $state.$current); - return (state && state.self) ? state.self : null; - }; - - function resolveState(state, params, paramsAreFiltered, inherited, dst, options) { - // Make a restricted $stateParams with only the parameters that apply to this state if - // necessary. In addition to being available to the controller and onEnter/onExit callbacks, - // we also need $stateParams to be available for any $injector calls we make during the - // dependency resolution process. - var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params); - var locals = { $stateParams: $stateParams }; - - // Resolve 'global' dependencies for the state, i.e. those not specific to a view. - // We're also including $stateParams in this; that way the parameters are restricted - // to the set that should be visible to the state, and are independent of when we update - // the global $state and $stateParams values. - dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state); - var promises = [dst.resolve.then(function (globals) { - dst.globals = globals; - })]; - if (inherited) promises.push(inherited); - - function resolveViews() { - var viewsPromises = []; - - // Resolve template and dependencies for all views. - forEach(state.views, function (view, name) { - var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {}); - injectables.$template = [ function () { - return $view.load(name, { view: view, locals: dst.globals, params: $stateParams, notify: options.notify }) || ''; - }]; - - viewsPromises.push($resolve.resolve(injectables, dst.globals, dst.resolve, state).then(function (result) { - // References to the controller (only instantiated at link time) - if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) { - var injectLocals = angular.extend({}, injectables, dst.globals); - result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals); - } else { - result.$$controller = view.controller; - } - // Provide access to the state itself for internal use - result.$$state = state; - result.$$controllerAs = view.controllerAs; - dst[name] = result; - })); - }); - - return $q.all(viewsPromises).then(function(){ - return dst.globals; - }); - } - - // Wait for all the promises and then return the activation object - return $q.all(promises).then(resolveViews).then(function (values) { - return dst; - }); - } - - return $state; - } - - function shouldSkipReload(to, toParams, from, fromParams, locals, options) { - // Return true if there are no differences in non-search (path/object) params, false if there are differences - function nonSearchParamsEqual(fromAndToState, fromParams, toParams) { - // Identify whether all the parameters that differ between `fromParams` and `toParams` were search params. - function notSearchParam(key) { - return fromAndToState.params[key].location != "search"; - } - var nonQueryParamKeys = fromAndToState.params.$$keys().filter(notSearchParam); - var nonQueryParams = pick.apply({}, [fromAndToState.params].concat(nonQueryParamKeys)); - var nonQueryParamSet = new $$UMFP.ParamSet(nonQueryParams); - return nonQueryParamSet.$$equals(fromParams, toParams); - } - - // If reload was not explicitly requested - // and we're transitioning to the same state we're already in - // and the locals didn't change - // or they changed in a way that doesn't merit reloading - // (reloadOnParams:false, or reloadOnSearch.false and only search params changed) - // Then return true. - if (!options.reload && to === from && - (locals === from.locals || (to.self.reloadOnSearch === false && nonSearchParamsEqual(from, fromParams, toParams)))) { - return true; - } - } -} - -angular.module('ui.router.state') - .factory('$stateParams', function () { return {}; }) - .provider('$state', $StateProvider); - - -$ViewProvider.$inject = []; -function $ViewProvider() { - - this.$get = $get; - /** - * @ngdoc object - * @name ui.router.state.$view - * - * @requires ui.router.util.$templateFactory - * @requires $rootScope - * - * @description - * - */ - $get.$inject = ['$rootScope', '$templateFactory']; - function $get( $rootScope, $templateFactory) { - return { - // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... }) - /** - * @ngdoc function - * @name ui.router.state.$view#load - * @methodOf ui.router.state.$view - * - * @description - * - * @param {string} name name - * @param {object} options option object. - */ - load: function load(name, options) { - var result, defaults = { - template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {} - }; - options = extend(defaults, options); - - if (options.view) { - result = $templateFactory.fromConfig(options.view, options.params, options.locals); - } - return result; - } - }; - } -} - -angular.module('ui.router.state').provider('$view', $ViewProvider); - -/** - * @ngdoc object - * @name ui.router.state.$uiViewScrollProvider - * - * @description - * Provider that returns the {@link ui.router.state.$uiViewScroll} service function. - */ -function $ViewScrollProvider() { - - var useAnchorScroll = false; - - /** - * @ngdoc function - * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll - * @methodOf ui.router.state.$uiViewScrollProvider - * - * @description - * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for - * scrolling based on the url anchor. - */ - this.useAnchorScroll = function () { - useAnchorScroll = true; - }; - - /** - * @ngdoc object - * @name ui.router.state.$uiViewScroll - * - * @requires $anchorScroll - * @requires $timeout - * - * @description - * When called with a jqLite element, it scrolls the element into view (after a - * `$timeout` so the DOM has time to refresh). - * - * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor, - * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}. - */ - this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) { - if (useAnchorScroll) { - return $anchorScroll; - } - - return function ($element) { - return $timeout(function () { - $element[0].scrollIntoView(); - }, 0, false); - }; - }]; -} - -angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider); - -var ngMajorVer = angular.version.major; -var ngMinorVer = angular.version.minor; -/** - * @ngdoc directive - * @name ui.router.state.directive:ui-view - * - * @requires ui.router.state.$state - * @requires $compile - * @requires $controller - * @requires $injector - * @requires ui.router.state.$uiViewScroll - * @requires $document - * - * @restrict ECA - * - * @description - * The ui-view directive tells $state where to place your templates. - * - * @param {string=} name A view name. The name should be unique amongst the other views in the - * same state. You can have views of the same name that live in different states. - * - * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window - * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll - * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you - * scroll ui-view elements into view when they are populated during a state activation. - * - * @param {string=} noanimation If truthy, the non-animated renderer will be selected (no animations - * will be applied to the ui-view) - * - * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) - * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.* - * - * @param {string=} onload Expression to evaluate whenever the view updates. - * - * @example - * A view can be unnamed or named. - *
- * 
- * 
- * - * - *
- *
- * - * You can only have one unnamed view within any template (or root html). If you are only using a - * single view and it is unnamed then you can populate it like so: - *
- * 
- * $stateProvider.state("home", { - * template: "

HELLO!

" - * }) - *
- * - * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`} - * config property, by name, in this case an empty name: - *
- * $stateProvider.state("home", {
- *   views: {
- *     "": {
- *       template: "

HELLO!

" - * } - * } - * }) - *
- * - * But typically you'll only use the views property if you name your view or have more than one view - * in the same template. There's not really a compelling reason to name a view if its the only one, - * but you could if you wanted, like so: - *
- * 
- *
- *
- * $stateProvider.state("home", {
- *   views: {
- *     "main": {
- *       template: "

HELLO!

" - * } - * } - * }) - *
- * - * Really though, you'll use views to set up multiple views: - *
- * 
- *
- *
- *
- * - *
- * $stateProvider.state("home", {
- *   views: {
- *     "": {
- *       template: "

HELLO!

" - * }, - * "chart": { - * template: "" - * }, - * "data": { - * template: "" - * } - * } - * }) - *
- * - * Examples for `autoscroll`: - * - *
- * 
- * 
- *
- * 
- * 
- * 
- * 
- * 
- */ -$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate']; -function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) { - - function getService() { - return ($injector.has) ? function(service) { - return $injector.has(service) ? $injector.get(service) : null; - } : function(service) { - try { - return $injector.get(service); - } catch (e) { - return null; - } - }; - } - - var service = getService(), - $animator = service('$animator'), - $animate = service('$animate'); - - // Returns a set of DOM manipulation functions based on which Angular version - // it should use - function getRenderer(attrs, scope) { - var statics = { - enter: function (element, target, cb) { target.after(element); cb(); }, - leave: function (element, cb) { element.remove(); cb(); } - }; - - if (!!attrs.noanimation) return statics; - - function animEnabled(element) { - if (ngMajorVer === 1 && ngMinorVer >= 4) return !!$animate.enabled(element); - if (ngMajorVer === 1 && ngMinorVer >= 2) return !!$animate.enabled(); - return (!!$animator); - } - - // ng 1.2+ - if ($animate) { - return { - enter: function(element, target, cb) { - if (!animEnabled(element)) { - statics.enter(element, target, cb); - } else if (angular.version.minor > 2) { - $animate.enter(element, null, target).then(cb); - } else { - $animate.enter(element, null, target, cb); - } - }, - leave: function(element, cb) { - if (!animEnabled(element)) { - statics.leave(element, cb); - } else if (angular.version.minor > 2) { - $animate.leave(element).then(cb); - } else { - $animate.leave(element, cb); - } - } - }; - } - - // ng 1.1.5 - if ($animator) { - var animate = $animator && $animator(scope, attrs); - - return { - enter: function(element, target, cb) {animate.enter(element, null, target); cb(); }, - leave: function(element, cb) { animate.leave(element); cb(); } - }; - } - - return statics; - } - - var directive = { - restrict: 'ECA', - terminal: true, - priority: 400, - transclude: 'element', - compile: function (tElement, tAttrs, $transclude) { - return function (scope, $element, attrs) { - var previousEl, currentEl, currentScope, latestLocals, - onloadExp = attrs.onload || '', - autoScrollExp = attrs.autoscroll, - renderer = getRenderer(attrs, scope); - - scope.$on('$stateChangeSuccess', function() { - updateView(false); - }); - - updateView(true); - - function cleanupLastView() { - var _previousEl = previousEl; - var _currentScope = currentScope; - - if (_currentScope) { - _currentScope._willBeDestroyed = true; - } - - function cleanOld() { - if (_previousEl) { - _previousEl.remove(); - } - - if (_currentScope) { - _currentScope.$destroy(); - } - } - - if (currentEl) { - renderer.leave(currentEl, function() { - cleanOld(); - previousEl = null; - }); - - previousEl = currentEl; - } else { - cleanOld(); - previousEl = null; - } - - currentEl = null; - currentScope = null; - } - - function updateView(firstTime) { - var newScope, - name = getUiViewName(scope, attrs, $element, $interpolate), - previousLocals = name && $state.$current && $state.$current.locals[name]; - - if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do - newScope = scope.$new(); - latestLocals = $state.$current.locals[name]; - - /** - * @ngdoc event - * @name ui.router.state.directive:ui-view#$viewContentLoading - * @eventOf ui.router.state.directive:ui-view - * @eventType emits on ui-view directive scope - * @description - * - * Fired once the view **begins loading**, *before* the DOM is rendered. - * - * @param {Object} event Event object. - * @param {string} viewName Name of the view. - */ - newScope.$emit('$viewContentLoading', name); - - var clone = $transclude(newScope, function(clone) { - renderer.enter(clone, $element, function onUiViewEnter() { - if(currentScope) { - currentScope.$emit('$viewContentAnimationEnded'); - } - - if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { - $uiViewScroll(clone); - } - }); - cleanupLastView(); - }); - - currentEl = clone; - currentScope = newScope; - /** - * @ngdoc event - * @name ui.router.state.directive:ui-view#$viewContentLoaded - * @eventOf ui.router.state.directive:ui-view - * @eventType emits on ui-view directive scope - * @description - * Fired once the view is **loaded**, *after* the DOM is rendered. - * - * @param {Object} event Event object. - * @param {string} viewName Name of the view. - */ - currentScope.$emit('$viewContentLoaded', name); - currentScope.$eval(onloadExp); - } - }; - } - }; - - return directive; -} - -$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate']; -function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) { - return { - restrict: 'ECA', - priority: -400, - compile: function (tElement) { - var initial = tElement.html(); - return function (scope, $element, attrs) { - var current = $state.$current, - name = getUiViewName(scope, attrs, $element, $interpolate), - locals = current && current.locals[name]; - - if (! locals) { - return; - } - - $element.data('$uiView', { name: name, state: locals.$$state }); - $element.html(locals.$template ? locals.$template : initial); - - var link = $compile($element.contents()); - - if (locals.$$controller) { - locals.$scope = scope; - locals.$element = $element; - var controller = $controller(locals.$$controller, locals); - if (locals.$$controllerAs) { - scope[locals.$$controllerAs] = controller; - } - $element.data('$ngControllerController', controller); - $element.children().data('$ngControllerController', controller); - } - - link(scope); - }; - } - }; -} - -/** - * Shared ui-view code for both directives: - * Given scope, element, and its attributes, return the view's name - */ -function getUiViewName(scope, attrs, element, $interpolate) { - var name = $interpolate(attrs.uiView || attrs.name || '')(scope); - var inherited = element.inheritedData('$uiView'); - return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : '')); -} - -angular.module('ui.router.state').directive('uiView', $ViewDirective); -angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill); - -function parseStateRef(ref, current) { - var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed; - if (preparsed) ref = current + '(' + preparsed[1] + ')'; - parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); - if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'"); - return { state: parsed[1], paramExpr: parsed[3] || null }; -} - -function stateContext(el) { - var stateData = el.parent().inheritedData('$uiView'); - - if (stateData && stateData.state && stateData.state.name) { - return stateData.state; - } -} - -function getTypeInfo(el) { - // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. - var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]'; - var isForm = el[0].nodeName === "FORM"; - - return { - attr: isForm ? "action" : (isSvg ? 'xlink:href' : 'href'), - isAnchor: el.prop("tagName").toUpperCase() === "A", - clickable: !isForm - }; -} - -function clickHook(el, $state, $timeout, type, current) { - return function(e) { - var button = e.which || e.button, target = current(); - - if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) { - // HACK: This is to allow ng-clicks to be processed before the transition is initiated: - var transition = $timeout(function() { - $state.go(target.state, target.params, target.options); - }); - e.preventDefault(); - - // if the state has no URL, ignore one preventDefault from the directive. - var ignorePreventDefaultCount = type.isAnchor && !target.href ? 1: 0; - - e.preventDefault = function() { - if (ignorePreventDefaultCount-- <= 0) $timeout.cancel(transition); - }; - } - }; -} - -function defaultOpts(el, $state) { - return { relative: stateContext(el) || $state.$current, inherit: true }; -} - -/** - * @ngdoc directive - * @name ui.router.state.directive:ui-sref - * - * @requires ui.router.state.$state - * @requires $timeout - * - * @restrict A - * - * @description - * A directive that binds a link (`` tag) to a state. If the state has an associated - * URL, the directive will automatically generate & update the `href` attribute via - * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking - * the link will trigger a state transition with optional parameters. - * - * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be - * handled natively by the browser. - * - * You can also use relative state paths within ui-sref, just like the relative - * paths passed to `$state.go()`. You just need to be aware that the path is relative - * to the state that the link lives in, in other words the state that loaded the - * template containing the link. - * - * You can specify options to pass to {@link ui.router.state.$state#go $state.go()} - * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`, - * and `reload`. - * - * @example - * Here's an example of how you'd use ui-sref and how it would compile. If you have the - * following template: - *
- * Home | About | Next page
- *
- * 
- * 
- * - * Then the compiled html would be (assuming Html5Mode is off and current state is contacts): - *
- * Home | About | Next page
- *
- * 
    - *
  • - * Joe - *
  • - *
  • - * Alice - *
  • - *
  • - * Bob - *
  • - *
- * - * Home - *
- * - * @param {string} ui-sref 'stateName' can be any valid absolute or relative state - * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()} - */ -$StateRefDirective.$inject = ['$state', '$timeout']; -function $StateRefDirective($state, $timeout) { - return { - restrict: 'A', - require: ['?^uiSrefActive', '?^uiSrefActiveEq'], - link: function(scope, element, attrs, uiSrefActive) { - var ref = parseStateRef(attrs.uiSref, $state.current.name); - var def = { state: ref.state, href: null, params: null }; - var type = getTypeInfo(element); - var active = uiSrefActive[1] || uiSrefActive[0]; - - def.options = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {}); - - var update = function(val) { - if (val) def.params = angular.copy(val); - def.href = $state.href(ref.state, def.params, def.options); - - if (active) active.$$addStateInfo(ref.state, def.params); - if (def.href !== null) attrs.$set(type.attr, def.href); - }; - - if (ref.paramExpr) { - scope.$watch(ref.paramExpr, function(val) { if (val !== def.params) update(val); }, true); - def.params = angular.copy(scope.$eval(ref.paramExpr)); - } - update(); - - if (!type.clickable) return; - element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; })); - } - }; -} - -/** - * @ngdoc directive - * @name ui.router.state.directive:ui-state - * - * @requires ui.router.state.uiSref - * - * @restrict A - * - * @description - * Much like ui-sref, but will accept named $scope properties to evaluate for a state definition, - * params and override options. - * - * @param {string} ui-state 'stateName' can be any valid absolute or relative state - * @param {Object} ui-state-params params to pass to {@link ui.router.state.$state#href $state.href()} - * @param {Object} ui-state-opts options to pass to {@link ui.router.state.$state#go $state.go()} - */ -$StateRefDynamicDirective.$inject = ['$state', '$timeout']; -function $StateRefDynamicDirective($state, $timeout) { - return { - restrict: 'A', - require: ['?^uiSrefActive', '?^uiSrefActiveEq'], - link: function(scope, element, attrs, uiSrefActive) { - var type = getTypeInfo(element); - var active = uiSrefActive[1] || uiSrefActive[0]; - var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null]; - var watch = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']'; - var def = { state: null, params: null, options: null, href: null }; - - function runStateRefLink (group) { - def.state = group[0]; def.params = group[1]; def.options = group[2]; - def.href = $state.href(def.state, def.params, def.options); - - if (active) active.$$addStateInfo(def.state, def.params); - if (def.href) attrs.$set(type.attr, def.href); - } - - scope.$watch(watch, runStateRefLink, true); - runStateRefLink(scope.$eval(watch)); - - if (!type.clickable) return; - element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; })); - } - }; -} - - -/** - * @ngdoc directive - * @name ui.router.state.directive:ui-sref-active - * - * @requires ui.router.state.$state - * @requires ui.router.state.$stateParams - * @requires $interpolate - * - * @restrict A - * - * @description - * A directive working alongside ui-sref to add classes to an element when the - * related ui-sref directive's state is active, and removing them when it is inactive. - * The primary use-case is to simplify the special appearance of navigation menus - * relying on `ui-sref`, by having the "active" state's menu button appear different, - * distinguishing it from the inactive menu items. - * - * ui-sref-active can live on the same element as ui-sref or on a parent element. The first - * ui-sref-active found at the same level or above the ui-sref will be used. - * - * Will activate when the ui-sref's target state or any child state is active. If you - * need to activate only when the ui-sref target state is active and *not* any of - * it's children, then you will use - * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq} - * - * @example - * Given the following template: - *
- * 
- * 
- * - * - * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins", - * the resulting HTML will appear as (note the 'active' class): - *
- * 
- * 
- * - * The class name is interpolated **once** during the directives link time (any further changes to the - * interpolated value are ignored). - * - * Multiple classes may be specified in a space-separated format: - *
- * 
    - *
  • - * link - *
  • - *
- *
- * - * It is also possible to pass ui-sref-active an expression that evaluates - * to an object hash, whose keys represent active class names and whose - * values represent the respective state names/globs. - * ui-sref-active will match if the current active state **includes** any of - * the specified state names/globs, even the abstract ones. - * - * @Example - * Given the following template, with "admin" being an abstract state: - *
- * 
- * Roles - *
- *
- * - * When the current state is "admin.roles" the "active" class will be applied - * to both the
and elements. It is important to note that the state - * names/globs passed to ui-sref-active shadow the state provided by ui-sref. - */ - -/** - * @ngdoc directive - * @name ui.router.state.directive:ui-sref-active-eq - * - * @requires ui.router.state.$state - * @requires ui.router.state.$stateParams - * @requires $interpolate - * - * @restrict A - * - * @description - * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate - * when the exact target state used in the `ui-sref` is active; no child states. - * - */ -$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate']; -function $StateRefActiveDirective($state, $stateParams, $interpolate) { - return { - restrict: "A", - controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) { - var states = [], activeClasses = {}, activeEqClass, uiSrefActive; - - // There probably isn't much point in $observing this - // uiSrefActive and uiSrefActiveEq share the same directive object with some - // slight difference in logic routing - activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope); - - try { - uiSrefActive = $scope.$eval($attrs.uiSrefActive); - } catch (e) { - // Do nothing. uiSrefActive is not a valid expression. - // Fall back to using $interpolate below - } - uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope); - if (isObject(uiSrefActive)) { - forEach(uiSrefActive, function(stateOrName, activeClass) { - if (isString(stateOrName)) { - var ref = parseStateRef(stateOrName, $state.current.name); - addState(ref.state, $scope.$eval(ref.paramExpr), activeClass); - } - }); - } - - // Allow uiSref to communicate with uiSrefActive[Equals] - this.$$addStateInfo = function (newState, newParams) { - // we already got an explicit state provided by ui-sref-active, so we - // shadow the one that comes from ui-sref - if (isObject(uiSrefActive) && states.length > 0) { - return; - } - addState(newState, newParams, uiSrefActive); - update(); - }; - - $scope.$on('$stateChangeSuccess', update); - - function addState(stateName, stateParams, activeClass) { - var state = $state.get(stateName, stateContext($element)); - var stateHash = createStateHash(stateName, stateParams); - - states.push({ - state: state || { name: stateName }, - params: stateParams, - hash: stateHash - }); - - activeClasses[stateHash] = activeClass; - } - - /** - * @param {string} state - * @param {Object|string} [params] - * @return {string} - */ - function createStateHash(state, params) { - if (!isString(state)) { - throw new Error('state should be a string'); - } - if (isObject(params)) { - return state + toJson(params); - } - params = $scope.$eval(params); - if (isObject(params)) { - return state + toJson(params); - } - return state; - } - - // Update route state - function update() { - for (var i = 0; i < states.length; i++) { - if (anyMatch(states[i].state, states[i].params)) { - addClass($element, activeClasses[states[i].hash]); - } else { - removeClass($element, activeClasses[states[i].hash]); - } - - if (exactMatch(states[i].state, states[i].params)) { - addClass($element, activeEqClass); - } else { - removeClass($element, activeEqClass); - } - } - } - - function addClass(el, className) { $timeout(function () { el.addClass(className); }); } - function removeClass(el, className) { el.removeClass(className); } - function anyMatch(state, params) { return $state.includes(state.name, params); } - function exactMatch(state, params) { return $state.is(state.name, params); } - - update(); - }] - }; -} - -angular.module('ui.router.state') - .directive('uiSref', $StateRefDirective) - .directive('uiSrefActive', $StateRefActiveDirective) - .directive('uiSrefActiveEq', $StateRefActiveDirective) - .directive('uiState', $StateRefDynamicDirective); - -/** - * @ngdoc filter - * @name ui.router.state.filter:isState - * - * @requires ui.router.state.$state - * - * @description - * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}. - */ -$IsStateFilter.$inject = ['$state']; -function $IsStateFilter($state) { - var isFilter = function (state, params) { - return $state.is(state, params); - }; - isFilter.$stateful = true; - return isFilter; -} - -/** - * @ngdoc filter - * @name ui.router.state.filter:includedByState - * - * @requires ui.router.state.$state - * - * @description - * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}. - */ -$IncludedByStateFilter.$inject = ['$state']; -function $IncludedByStateFilter($state) { - var includesFilter = function (state, params, options) { - return $state.includes(state, params, options); - }; - includesFilter.$stateful = true; - return includesFilter; -} - -angular.module('ui.router.state') - .filter('isState', $IsStateFilter) - .filter('includedByState', $IncludedByStateFilter); -})(window, window.angular); \ No newline at end of file +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define("angular-ui-router", [], factory); + else if(typeof exports === 'object') + exports["angular-ui-router"] = factory(); + else + root["angular-ui-router"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Main entry point for angular 1.x build + * @module ng1 + */ + /** for typedoc */ + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + __export(__webpack_require__(1)); + __export(__webpack_require__(53)); + __export(__webpack_require__(54)); + __webpack_require__(56); + __webpack_require__(57); + __webpack_require__(58); + __webpack_require__(59); + Object.defineProperty(exports, "__esModule", { value: true }); + exports.default = "ui.router"; + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module common */ /** */ + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + __export(__webpack_require__(2)); + __export(__webpack_require__(20)); + __export(__webpack_require__(44)); + __export(__webpack_require__(40)); + __export(__webpack_require__(17)); + __export(__webpack_require__(13)); + __export(__webpack_require__(45)); + __export(__webpack_require__(49)); + __export(__webpack_require__(51)); + var router_1 = __webpack_require__(52); + exports.UIRouter = router_1.UIRouter; + + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** @module common */ /** for typedoc */ + __export(__webpack_require__(3)); + __export(__webpack_require__(6)); + __export(__webpack_require__(7)); + __export(__webpack_require__(5)); + __export(__webpack_require__(4)); + __export(__webpack_require__(8)); + __export(__webpack_require__(9)); + __export(__webpack_require__(12)); + + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Random utility functions used in the UI-Router code + * + * @preferred @module common + */ /** for typedoc */ + "use strict"; + var predicates_1 = __webpack_require__(4); + var hof_1 = __webpack_require__(5); + var angular = window.angular || {}; + exports.fromJson = angular.fromJson || JSON.parse.bind(JSON); + exports.toJson = angular.toJson || JSON.stringify.bind(JSON); + exports.copy = angular.copy || _copy; + exports.forEach = angular.forEach || _forEach; + exports.extend = angular.extend || _extend; + exports.equals = angular.equals || _equals; + exports.identity = function (x) { return x; }; + exports.noop = function () { return undefined; }; + exports.abstractKey = 'abstract'; + /** + * Binds and copies functions onto an object + * + * Takes functions from the 'from' object, binds those functions to the _this object, and puts the bound functions + * on the 'to' object. + * + * This example creates an new class instance whose functions are prebound to the new'd object. + * @example + * ``` + * + * class Foo { + * constructor(data) { + * // Binds all functions from Foo.prototype to 'this', + * // then copies them to 'this' + * bindFunctions(Foo.prototype, this, this); + * this.data = data; + * } + * + * log() { + * console.log(this.data); + * } + * } + * + * let myFoo = new Foo([1,2,3]); + * var logit = myFoo.log; + * logit(); // logs [1, 2, 3] from the myFoo 'this' instance + * ``` + * + * This example creates a bound version of a service function, and copies it to another object + * @example + * ``` + * + * var SomeService = { + * this.data = [3, 4, 5]; + * this.log = function() { + * console.log(this.data); + * } + * } + * + * // Constructor fn + * function OtherThing() { + * // Binds all functions from SomeService to SomeService, + * // then copies them to 'this' + * bindFunctions(SomeService, this, SomeService); + * } + * + * let myOtherThing = new OtherThing(); + * myOtherThing.log(); // logs [3, 4, 5] from SomeService's 'this' + * ``` + * + * @param from The object which contains the functions to be bound + * @param to The object which will receive the bound functions + * @param bindTo The object which the functions will be bound to + * @param fnNames The function names which will be bound (Defaults to all the functions found on the 'from' object) + */ + function bindFunctions(from, to, bindTo, fnNames) { + if (fnNames === void 0) { fnNames = Object.keys(from); } + return fnNames.filter(function (name) { return typeof from[name] === 'function'; }) + .forEach(function (name) { return to[name] = from[name].bind(bindTo); }); + } + exports.bindFunctions = bindFunctions; + /** + * prototypal inheritance helper. + * Creates a new object which has `parent` object as its prototype, and then copies the properties from `extra` onto it + */ + exports.inherit = function (parent, extra) { + return exports.extend(new (exports.extend(function () { }, { prototype: parent }))(), extra); + }; + /** + * Given an arguments object, converts the arguments at index idx and above to an array. + * This is similar to es6 rest parameters. + * + * Optionally, the argument at index idx may itself already be an array. + * + * For example, + * given either: + * arguments = [ obj, "foo", "bar" ] + * or: + * arguments = [ obj, ["foo", "bar"] ] + * then: + * restArgs(arguments, 1) == ["foo", "bar"] + * + * This allows functions like pick() to be implemented such that it allows either a bunch + * of string arguments (like es6 rest parameters), or a single array of strings: + * + * given: + * var obj = { foo: 1, bar: 2, baz: 3 }; + * then: + * pick(obj, "foo", "bar"); // returns { foo: 1, bar: 2 } + * pick(obj, ["foo", "bar"]); // returns { foo: 1, bar: 2 } + */ + var restArgs = function (args, idx) { + if (idx === void 0) { idx = 0; } + return Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(args, idx)); + }; + /** Given an array, returns true if the object is found in the array, (using indexOf) */ + var inArray = function (array, obj) { return array.indexOf(obj) !== -1; }; + /** Given an array, and an item, if the item is found in the array, it removes it (in-place). The same array is returned */ + exports.removeFrom = hof_1.curry(function (array, obj) { + var idx = array.indexOf(obj); + if (idx >= 0) + array.splice(idx, 1); + return array; + }); + /** + * Applies a set of defaults to an options object. The options object is filtered + * to only those properties of the objects in the defaultsList. + * Earlier objects in the defaultsList take precedence when applying defaults. + */ + function defaults(opts) { + if (opts === void 0) { opts = {}; } + var defaultsList = []; + for (var _i = 1; _i < arguments.length; _i++) { + defaultsList[_i - 1] = arguments[_i]; + } + var defaults = merge.apply(null, [{}].concat(defaultsList)); + return exports.extend({}, defaults, pick(opts || {}, Object.keys(defaults))); + } + exports.defaults = defaults; + /** + * Merges properties from the list of objects to the destination object. + * If a property already exists in the destination object, then it is not overwritten. + */ + function merge(dst) { + var objs = []; + for (var _i = 1; _i < arguments.length; _i++) { + objs[_i - 1] = arguments[_i]; + } + exports.forEach(objs, function (obj) { + exports.forEach(obj, function (value, key) { + if (!dst.hasOwnProperty(key)) + dst[key] = value; + }); + }); + return dst; + } + exports.merge = merge; + /** Reduce function that merges each element of the list into a single object, using extend */ + exports.mergeR = function (memo, item) { return exports.extend(memo, item); }; + /** + * 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] !== second.path[n]) + break; + path.push(first.path[n]); + } + return path; + } + exports.ancestors = ancestors; + /** + * 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 === void 0) { keys = Object.keys(a); } + 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; + } + exports.equalForKeys = equalForKeys; + function pickOmitImpl(predicate, obj) { + var objCopy = {}, keys = restArgs(arguments, 2); + for (var key in obj) { + if (predicate(keys, key)) + objCopy[key] = obj[key]; + } + return objCopy; + } + /** Return a copy of the object only containing the whitelisted properties. */ + function pick(obj) { return pickOmitImpl.apply(null, [inArray].concat(restArgs(arguments))); } + exports.pick = pick; + /** Return a copy of the object omitting the blacklisted properties. */ + function omit(obj) { return pickOmitImpl.apply(null, [hof_1.not(inArray)].concat(restArgs(arguments))); } + exports.omit = omit; + /** + * Maps an array, or object to a property (by name) + */ + function pluck(collection, propName) { + return map(collection, hof_1.prop(propName)); + } + exports.pluck = pluck; + /** Filters an Array or an Object's properties based on a predicate */ + function filter(collection, callback) { + var arr = predicates_1.isArray(collection), result = arr ? [] : {}; + var accept = arr ? function (x) { return result.push(x); } : function (x, key) { return result[key] = x; }; + exports.forEach(collection, function (item, i) { + if (callback(item, i)) + accept(item, i); + }); + return result; + } + exports.filter = filter; + /** Finds an object from an array, or a property of an object, that matches a predicate */ + function find(collection, callback) { + var result; + exports.forEach(collection, function (item, i) { + if (result) + return; + if (callback(item, i)) + result = item; + }); + return result; + } + exports.find = find; + /** Given an object, returns a new object, where each property is transformed by the callback function */ + exports.mapObj = map; + /** Maps an array or object properties using a callback function */ + function map(collection, callback) { + var result = predicates_1.isArray(collection) ? [] : {}; + exports.forEach(collection, function (item, i) { return result[i] = callback(item, i); }); + return result; + } + exports.map = map; + /** + * Given an object, return its enumerable property values + * + * @example + * ``` + * + * let foo = { a: 1, b: 2, c: 3 } + * let vals = values(foo); // [ 1, 2, 3 ] + * ``` + */ + exports.values = function (obj) { return Object.keys(obj).map(function (key) { return obj[key]; }); }; + /** + * Reduce function that returns true if all of the values are truthy. + * + * @example + * ``` + * + * let vals = [ 1, true, {}, "hello world"]; + * vals.reduce(allTrueR, true); // true + * + * vals.push(0); + * vals.reduce(allTrueR, true); // false + * ``` + */ + exports.allTrueR = function (memo, elem) { return memo && elem; }; + /** + * Reduce function that returns true if any of the values are truthy. + * + * * @example + * ``` + * + * let vals = [ 0, null, undefined ]; + * vals.reduce(anyTrueR, true); // false + * + * vals.push("hello world"); + * vals.reduce(anyTrueR, true); // true + * ``` + */ + exports.anyTrueR = function (memo, elem) { return memo || elem; }; + /** + * Reduce function which un-nests a single level of arrays + * @example + * ``` + * + * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ]; + * input.reduce(unnestR, []) // [ "a", "b", "c", "d", [ "double, "nested" ] ] + * ``` + */ + exports.unnestR = function (memo, elem) { return memo.concat(elem); }; + /** + * Reduce function which recursively un-nests all arrays + * + * @example + * ``` + * + * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ]; + * input.reduce(unnestR, []) // [ "a", "b", "c", "d", "double, "nested" ] + * ``` + */ + exports.flattenR = function (memo, elem) { return predicates_1.isArray(elem) ? memo.concat(elem.reduce(exports.flattenR, [])) : pushR(memo, elem); }; + /** Reduce function that pushes an object to an array, then returns the array. Mostly just for [[flattenR]] */ + function pushR(arr, obj) { arr.push(obj); return arr; } + /** + * Return a new array with a single level of arrays unnested. + * + * @example + * ``` + * + * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ]; + * unnest(input) // [ "a", "b", "c", "d", [ "double, "nested" ] ] + * ``` + */ + exports.unnest = function (arr) { return arr.reduce(exports.unnestR, []); }; + /** + * Return a completely flattened version of an array. + * + * @example + * ``` + * + * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ]; + * flatten(input) // [ "a", "b", "c", "d", "double, "nested" ] + * ``` + */ + exports.flatten = function (arr) { return arr.reduce(exports.flattenR, []); }; + /** + * Given a .filter Predicate, builds a .filter Predicate which throws an error if any elements do not pass. + * @example + * ``` + * + * let isNumber = (obj) => typeof(obj) === 'number'; + * let allNumbers = [ 1, 2, 3, 4, 5 ]; + * allNumbers.filter(assertPredicate(isNumber)); //OK + * + * let oneString = [ 1, 2, 3, 4, "5" ]; + * oneString.filter(assertPredicate(isNumber, "Not all numbers")); // throws Error(""Not all numbers""); + * ``` + */ + function assertPredicate(predicate, errMsg) { + if (errMsg === void 0) { errMsg = "assert failure"; } + return function (obj) { + if (!predicate(obj)) { + throw new Error(predicates_1.isFunction(errMsg) ? errMsg(obj) : errMsg); + } + return true; + }; + } + exports.assertPredicate = assertPredicate; + /** + * Like _.pairs: Given an object, returns an array of key/value pairs + * + * @example + * ``` + * + * pairs({ foo: "FOO", bar: "BAR }) // [ [ "foo", "FOO" ], [ "bar": "BAR" ] ] + * ``` + */ + exports.pairs = function (object) { return Object.keys(object).map(function (key) { return [key, object[key]]; }); }; + /** + * Given two or more parallel arrays, returns an array of tuples where + * each tuple is composed of [ a[i], b[i], ... z[i] ] + * + * @example + * ``` + * + * let foo = [ 0, 2, 4, 6 ]; + * let bar = [ 1, 3, 5, 7 ]; + * let baz = [ 10, 30, 50, 70 ]; + * arrayTuples(foo, bar); // [ [0, 1], [2, 3], [4, 5], [6, 7] ] + * arrayTuples(foo, bar, baz); // [ [0, 1, 10], [2, 3, 30], [4, 5, 50], [6, 7, 70] ] + * ``` + */ + function arrayTuples() { + var arrayArgs = []; + for (var _i = 0; _i < arguments.length; _i++) { + arrayArgs[_i - 0] = arguments[_i]; + } + if (arrayArgs.length === 0) + return []; + var length = arrayArgs.reduce(function (min, arr) { return Math.min(arr.length, min); }, 9007199254740991); // aka 2^53 − 1 aka Number.MAX_SAFE_INTEGER + return Array.apply(null, Array(length)).map(function (ignored, idx) { return arrayArgs.map(function (arr) { return arr[idx]; }); }); + } + exports.arrayTuples = arrayTuples; + /** + * Reduce function which builds an object from an array of [key, value] pairs. + * + * Each iteration sets the key/val pair on the memo object, then returns the memo for the next iteration. + * + * Each keyValueTuple should be an array with values [ key: string, value: any ] + * + * @example + * ``` + * + * var pairs = [ ["fookey", "fooval"], ["barkey", "barval"] ] + * + * var pairsToObj = pairs.reduce((memo, pair) => applyPairs(memo, pair), {}) + * // pairsToObj == { fookey: "fooval", barkey: "barval" } + * + * // Or, more simply: + * var pairsToObj = pairs.reduce(applyPairs, {}) + * // pairsToObj == { fookey: "fooval", barkey: "barval" } + * ``` + */ + function applyPairs(memo, keyValTuple) { + var key, value; + if (predicates_1.isArray(keyValTuple)) + key = keyValTuple[0], value = keyValTuple[1]; + if (!predicates_1.isString(key)) + throw new Error("invalid parameters to applyPairs"); + memo[key] = value; + return memo; + } + exports.applyPairs = applyPairs; + /** Get the last element of an array */ + function tail(arr) { + return arr.length && arr[arr.length - 1] || undefined; + } + exports.tail = tail; + /** + * shallow copy from src to dest + * + * note: This is a shallow copy, while angular.copy is a deep copy. + * ui-router uses `copy` only to make copies of state parameters. + */ + function _copy(src, dest) { + if (dest) + Object.keys(dest).forEach(function (key) { return delete dest[key]; }); + if (!dest) + dest = {}; + return exports.extend(dest, src); + } + function _forEach(obj, cb, _this) { + if (predicates_1.isArray(obj)) + return obj.forEach(cb, _this); + Object.keys(obj).forEach(function (key) { return cb(obj[key], key); }); + } + function _copyProps(to, from) { Object.keys(from).forEach(function (key) { return to[key] = from[key]; }); return to; } + function _extend(toObj, rest) { + return restArgs(arguments, 1).filter(exports.identity).reduce(_copyProps, toObj); + } + function _equals(o1, o2) { + if (o1 === o2) + return true; + if (o1 === null || o2 === null) + return false; + if (o1 !== o1 && o2 !== o2) + return true; // NaN === NaN + var t1 = typeof o1, t2 = typeof o2; + if (t1 !== t2 || t1 !== 'object') + return false; + var tup = [o1, o2]; + if (hof_1.all(predicates_1.isArray)(tup)) + return _arraysEq(o1, o2); + if (hof_1.all(predicates_1.isDate)(tup)) + return o1.getTime() === o2.getTime(); + if (hof_1.all(predicates_1.isRegExp)(tup)) + return o1.toString() === o2.toString(); + if (hof_1.all(predicates_1.isFunction)(tup)) + return true; // meh + var predicates = [predicates_1.isFunction, predicates_1.isArray, predicates_1.isDate, predicates_1.isRegExp]; + if (predicates.map(hof_1.any).reduce(function (b, fn) { return b || !!fn(tup); }, false)) + return false; + var key, keys = {}; + for (key in o1) { + if (!_equals(o1[key], o2[key])) + return false; + keys[key] = true; + } + for (key in o2) { + if (!keys[key]) + return false; + } + return true; + } + function _arraysEq(a1, a2) { + if (a1.length !== a2.length) + return false; + return arrayTuples(a1, a2).reduce(function (b, t) { return b && _equals(t[0], t[1]); }, true); + } + // + //const _addToGroup = (result, keyFn) => (item) => + // (result[keyFn(item)] = result[keyFn(item)] || []).push(item) && result; + //const groupBy = (array, keyFn) => array.reduce((memo, item) => _addToGroup(memo, keyFn), {}); + // + // + + +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** Predicates @module common_predicates */ /** */ + var hof_1 = __webpack_require__(5); + var toStr = Object.prototype.toString; + var tis = function (t) { return function (x) { return typeof (x) === t; }; }; + exports.isUndefined = tis('undefined'); + exports.isDefined = hof_1.not(exports.isUndefined); + exports.isNull = function (o) { return o === null; }; + exports.isFunction = tis('function'); + exports.isNumber = tis('number'); + exports.isString = tis('string'); + exports.isObject = function (x) { return x !== null && typeof x === 'object'; }; + exports.isArray = Array.isArray; + exports.isDate = function (x) { return toStr.call(x) === '[object Date]'; }; + exports.isRegExp = function (x) { return toStr.call(x) === '[object RegExp]'; }; + /** + * Predicate which checks if a value is injectable + * + * A value is "injectable" if it is a function, or if it is an ng1 array-notation-style array + * where all the elements in the array are Strings, except the last one, which is a Function + */ + function isInjectable(val) { + if (exports.isArray(val) && val.length) { + var head = val.slice(0, -1), tail = val.slice(-1); + return !(head.filter(hof_1.not(exports.isString)).length || tail.filter(hof_1.not(exports.isFunction)).length); + } + return exports.isFunction(val); + } + exports.isInjectable = isInjectable; + /** + * Predicate which checks if a value looks like a Promise + * + * It is probably a Promise if it's an object, and it has a `then` property which is a Function + */ + exports.isPromise = hof_1.and(exports.isObject, hof_1.pipe(hof_1.prop('then'), exports.isFunction)); + + +/***/ }, +/* 5 */ +/***/ function(module, exports) { + + /** + * Higher order functions + * + * @module common_hof + */ + "use strict"; + /** + * Returns a new function for [Partial Application](https://en.wikipedia.org/wiki/Partial_application) of the original function. + * + * Given a function with N parameters, returns a new function that supports partial application. + * The new function accepts anywhere from 1 to N parameters. When that function is called with M parameters, + * where M is less than N, it returns a new function that accepts the remaining parameters. It continues to + * accept more parameters until all N parameters have been supplied. + * + * + * This contrived example uses a partially applied function as an predicate, which returns true + * if an object is found in both arrays. + * @example + * ``` + * // returns true if an object is in both of the two arrays + * function inBoth(array1, array2, object) { + * return array1.indexOf(object) !== -1 && + * array2.indexOf(object) !== 1; + * } + * let obj1, obj2, obj3, obj4, obj5, obj6, obj7 + * let foos = [obj1, obj3] + * let bars = [obj3, obj4, obj5] + * + * // A curried "copy" of inBoth + * let curriedInBoth = curry(inBoth); + * // Partially apply both the array1 and array2 + * let inFoosAndBars = curriedInBoth(foos, bars); + * + * // Supply the final argument; since all arguments are + * // supplied, the original inBoth function is then called. + * let obj1InBoth = inFoosAndBars(obj1); // false + * + * // Use the inFoosAndBars as a predicate. + * // Filter, on each iteration, supplies the final argument + * let allObjs = [ obj1, obj2, obj3, obj4, obj5, obj6, obj7 ]; + * let foundInBoth = allObjs.filter(inFoosAndBars); // [ obj3 ] + * + * ``` + * + * Stolen from: http://stackoverflow.com/questions/4394747/javascript-curry-function + * + * @param fn + * @returns {*|function(): (*|any)} + */ + function curry(fn) { + var initial_args = [].slice.apply(arguments, [1]); + var func_args_length = fn.length; + function curried(args) { + if (args.length >= func_args_length) + return fn.apply(null, args); + return function () { + return curried(args.concat([].slice.apply(arguments))); + }; + } + return curried(initial_args); + } + exports.curry = curry; + /** + * Given a varargs list of functions, returns a function that composes the argument functions, right-to-left + * given: f(x), g(x), h(x) + * let composed = compose(f,g,h) + * then, composed is: f(g(h(x))) + */ + function compose() { + var args = arguments; + var start = args.length - 1; + return function () { + var i = start, result = args[start].apply(this, arguments); + while (i--) + result = args[i].call(this, result); + return result; + }; + } + exports.compose = compose; + /** + * Given a varargs list of functions, returns a function that is composes the argument functions, left-to-right + * given: f(x), g(x), h(x) + * let piped = pipe(f,g,h); + * then, piped is: h(g(f(x))) + */ + function pipe() { + var funcs = []; + for (var _i = 0; _i < arguments.length; _i++) { + funcs[_i - 0] = arguments[_i]; + } + return compose.apply(null, [].slice.call(arguments).reverse()); + } + exports.pipe = pipe; + /** + * Given a property name, returns a function that returns that property from an object + * let obj = { foo: 1, name: "blarg" }; + * let getName = prop("name"); + * getName(obj) === "blarg" + */ + exports.prop = function (name) { return function (obj) { return obj && obj[name]; }; }; + /** + * Given a property name and a value, returns a function that returns a boolean based on whether + * the passed object has a property that matches the value + * let obj = { foo: 1, name: "blarg" }; + * let getName = propEq("name", "blarg"); + * getName(obj) === true + */ + exports.propEq = curry(function (name, val, obj) { return obj && obj[name] === val; }); + /** + * Given a dotted property name, returns a function that returns a nested property from an object, or undefined + * let obj = { id: 1, nestedObj: { foo: 1, name: "blarg" }, }; + * let getName = prop("nestedObj.name"); + * getName(obj) === "blarg" + * let propNotFound = prop("this.property.doesnt.exist"); + * propNotFound(obj) === undefined + */ + exports.parse = function (name) { return pipe.apply(null, name.split(".").map(exports.prop)); }; + /** + * Given a function that returns a truthy or falsey value, returns a + * function that returns the opposite (falsey or truthy) value given the same inputs + */ + exports.not = function (fn) { return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i - 0] = arguments[_i]; + } + return !fn.apply(null, args); + }; }; + /** + * Given two functions that return truthy or falsey values, returns a function that returns truthy + * if both functions return truthy for the given arguments + */ + function and(fn1, fn2) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i - 0] = arguments[_i]; + } + return fn1.apply(null, args) && fn2.apply(null, args); + }; + } + exports.and = and; + /** + * Given two functions that return truthy or falsey values, returns a function that returns truthy + * if at least one of the functions returns truthy for the given arguments + */ + function or(fn1, fn2) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i - 0] = arguments[_i]; + } + return fn1.apply(null, args) || fn2.apply(null, args); + }; + } + exports.or = or; + /** + * Check if all the elements of an array match a predicate function + * + * @param fn1 a predicate function `fn1` + * @returns a function which takes an array and returns true if `fn1` is true for all elements of the array + */ + exports.all = function (fn1) { return function (arr) { return arr.reduce(function (b, x) { return b && !!fn1(x); }, true); }; }; + exports.any = function (fn1) { return function (arr) { return arr.reduce(function (b, x) { return b || !!fn1(x); }, false); }; }; + exports.none = exports.not(exports.any); + /** Given a class, returns a Predicate function that returns true if the object is of that class */ + exports.is = function (ctor) { return function (obj) { return (obj != null && obj.constructor === ctor || obj instanceof ctor); }; }; + /** Given a value, returns a Predicate function that returns true if another value is === equal to the original value */ + exports.eq = function (val) { return function (other) { return val === other; }; }; + /** Given a value, returns a function which returns the value */ + exports.val = function (v) { return function () { return v; }; }; + function invoke(fnName, args) { + return function (obj) { return obj[fnName].apply(obj, args); }; + } + exports.invoke = invoke; + /** + * Sorta like Pattern Matching (a functional programming conditional construct) + * + * See http://c2.com/cgi/wiki?PatternMatching + * + * This is a conditional construct which allows a series of predicates and output functions + * to be checked and then applied. Each predicate receives the input. If the predicate + * returns truthy, then its matching output function (mapping function) is provided with + * the input and, then the result is returned. + * + * Each combination (2-tuple) of predicate + output function should be placed in an array + * of size 2: [ predicate, mapFn ] + * + * These 2-tuples should be put in an outer array. + * + * @example + * ``` + * + * // Here's a 2-tuple where the first element is the isString predicate + * // and the second element is a function that returns a description of the input + * let firstTuple = [ angular.isString, (input) => `Heres your string ${input}` ]; + * + * // Second tuple: predicate "isNumber", mapfn returns a description + * let secondTuple = [ angular.isNumber, (input) => `(${input}) That's a number!` ]; + * + * let third = [ (input) => input === null, (input) => `Oh, null...` ]; + * + * let fourth = [ (input) => input === undefined, (input) => `notdefined` ]; + * + * let descriptionOf = pattern([ firstTuple, secondTuple, third, fourth ]); + * + * console.log(descriptionOf(undefined)); // 'notdefined' + * console.log(descriptionOf(55)); // '(55) That's a number!' + * console.log(descriptionOf("foo")); // 'Here's your string foo' + * ``` + * + * @param struct A 2D array. Each element of the array should be an array, a 2-tuple, + * with a Predicate and a mapping/output function + * @returns {function(any): *} + */ + function pattern(struct) { + return function (x) { + for (var i = 0; i < struct.length; i++) { + if (struct[i][0](x)) + return struct[i][1](x); + } + }; + } + exports.pattern = pattern; + + +/***/ }, +/* 6 */ +/***/ function(module, exports) { + + /** + * This module is a stub for core services such as Dependency Injection or Browser Location. + * Core services may be implemented by a specific framework, such as ng1 or ng2, or be pure javascript. + * + * @module common + */ + "use strict"; + /** for typedoc */ + //import {IQService} from "angular"; + //import {IInjectorService} from "angular"; + var notImplemented = function (fnname) { return function () { + throw new Error(fnname + "(): No coreservices implementation for UI-Router is loaded. You should include one of: ['angular1.js']"); + }; }; + var services = { + $q: undefined, + $injector: undefined, + location: {}, + locationConfig: {}, + template: {} + }; + exports.services = services; + ["replace", "url", "path", "search", "hash", "onChange"] + .forEach(function (key) { return services.location[key] = notImplemented(key); }); + ["port", "protocol", "host", "baseHref", "html5Mode", "hashPrefix"] + .forEach(function (key) { return services.locationConfig[key] = notImplemented(key); }); + + +/***/ }, +/* 7 */ +/***/ function(module, exports) { + + "use strict"; + /** @module state */ /** for typedoc */ + var Glob = (function () { + function Glob(text) { + this.text = text; + this.glob = text.split('.'); + } + Glob.prototype.matches = function (name) { + var segments = name.split('.'); + // match single stars + for (var i = 0, l = this.glob.length; i < l; i++) { + if (this.glob[i] === '*') + segments[i] = '*'; + } + // match greedy starts + if (this.glob[0] === '**') { + segments = segments.slice(segments.indexOf(this.glob[1])); + segments.unshift('**'); + } + // match greedy ends + if (this.glob[this.glob.length - 1] === '**') { + segments.splice(segments.indexOf(this.glob[this.glob.length - 2]) + 1, Number.MAX_VALUE); + segments.push('**'); + } + if (this.glob.length != segments.length) + return false; + return segments.join('') === this.glob.join(''); + }; + Glob.is = function (text) { + return text.indexOf('*') > -1; + }; + Glob.fromString = function (text) { + if (!this.is(text)) + return null; + return new Glob(text); + }; + return Glob; + }()); + exports.Glob = Glob; + + +/***/ }, +/* 8 */ +/***/ function(module, exports) { + + /** @module common */ /** for typedoc */ + "use strict"; + var Queue = (function () { + function Queue(_items, _limit) { + if (_items === void 0) { _items = []; } + if (_limit === void 0) { _limit = null; } + this._items = _items; + this._limit = _limit; + } + Queue.prototype.enqueue = function (item) { + var items = this._items; + items.push(item); + if (this._limit && items.length > this._limit) + items.shift(); + return item; + }; + Queue.prototype.dequeue = function () { + if (this.size()) + return this._items.splice(0, 1)[0]; + }; + Queue.prototype.clear = function () { + var current = this._items; + this._items = []; + return current; + }; + Queue.prototype.size = function () { + return this._items.length; + }; + Queue.prototype.remove = function (item) { + var idx = this._items.indexOf(item); + return idx > -1 && this._items.splice(idx, 1)[0]; + }; + Queue.prototype.peekTail = function () { + return this._items[this._items.length - 1]; + }; + Queue.prototype.peekHead = function () { + if (this.size()) + return this._items[0]; + }; + return Queue; + }()); + exports.Queue = Queue; + + +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module common_strings */ /** */ + "use strict"; + var predicates_1 = __webpack_require__(4); + var rejectFactory_1 = __webpack_require__(10); + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var transition_1 = __webpack_require__(11); + var resolvable_1 = __webpack_require__(32); + /** + * Returns a string shortened to a maximum length + * + * If the string is already less than the `max` length, return the string. + * Else return the string, shortened to `max - 3` and append three dots ("..."). + * + * @param max the maximum length of the string to return + * @param str the input string + */ + function maxLength(max, str) { + if (str.length <= max) + return str; + return str.substr(0, max - 3) + "..."; + } + exports.maxLength = maxLength; + /** + * Returns a string, with spaces added to the end, up to a desired str length + * + * If the string is already longer than the desired length, return the string. + * Else returns the string, with extra spaces on the end, such that it reaches `length` characters. + * + * @param length the desired length of the string to return + * @param str the input string + */ + function padString(length, str) { + while (str.length < length) + str += " "; + return str; + } + exports.padString = padString; + exports.kebobString = function (camelCase) { return camelCase.replace(/([A-Z])/g, function ($1) { return "-" + $1.toLowerCase(); }); }; + function _toJson(obj) { + return JSON.stringify(obj); + } + function _fromJson(json) { + return predicates_1.isString(json) ? JSON.parse(json) : json; + } + function promiseToString(p) { + if (hof_1.is(rejectFactory_1.TransitionRejection)(p.reason)) + return p.reason.toString(); + return "Promise(" + JSON.stringify(p) + ")"; + } + function functionToString(fn) { + var fnStr = fnToString(fn); + var namedFunctionMatch = fnStr.match(/^(function [^ ]+\([^)]*\))/); + return namedFunctionMatch ? namedFunctionMatch[1] : fnStr; + } + exports.functionToString = functionToString; + function fnToString(fn) { + var _fn = predicates_1.isArray(fn) ? fn.slice(-1)[0] : fn; + return _fn && _fn.toString() || "undefined"; + } + exports.fnToString = fnToString; + var stringifyPattern = hof_1.pattern([ + [hof_1.not(predicates_1.isDefined), hof_1.val("undefined")], + [predicates_1.isNull, hof_1.val("null")], + [predicates_1.isPromise, promiseToString], + [hof_1.is(transition_1.Transition), hof_1.invoke("toString")], + [hof_1.is(resolvable_1.Resolvable), hof_1.invoke("toString")], + [predicates_1.isInjectable, functionToString], + [hof_1.val(true), common_1.identity] + ]); + function stringify(o) { + var seen = []; + function format(val) { + if (predicates_1.isObject(val)) { + if (seen.indexOf(val) !== -1) + return '[circular ref]'; + seen.push(val); + } + return stringifyPattern(val); + } + return JSON.stringify(o, function (key, val) { return format(val); }).replace(/\\"/g, '"'); + } + exports.stringify = stringify; + + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module transition */ /** for typedoc */ + "use strict"; + var common_1 = __webpack_require__(3); + var coreservices_1 = __webpack_require__(6); + var strings_1 = __webpack_require__(9); + (function (RejectType) { + RejectType[RejectType["SUPERSEDED"] = 2] = "SUPERSEDED"; + RejectType[RejectType["ABORTED"] = 3] = "ABORTED"; + RejectType[RejectType["INVALID"] = 4] = "INVALID"; + RejectType[RejectType["IGNORED"] = 5] = "IGNORED"; + })(exports.RejectType || (exports.RejectType = {})); + var RejectType = exports.RejectType; + var TransitionRejection = (function () { + function TransitionRejection(type, message, detail) { + common_1.extend(this, { + type: type, + message: message, + detail: detail + }); + } + TransitionRejection.prototype.toString = function () { + var detailString = function (d) { return d && d.toString !== Object.prototype.toString ? d.toString() : strings_1.stringify(d); }; + var type = this.type, message = this.message, detail = detailString(this.detail); + return "TransitionRejection(type: " + type + ", message: " + message + ", detail: " + detail + ")"; + }; + return TransitionRejection; + }()); + exports.TransitionRejection = TransitionRejection; + var RejectFactory = (function () { + function RejectFactory() { + } + RejectFactory.prototype.superseded = function (detail, options) { + var message = "The transition has been superseded by a different transition (see detail)."; + var reason = new TransitionRejection(RejectType.SUPERSEDED, message, detail); + if (options && options.redirected) { + reason.redirected = true; + } + return common_1.extend(coreservices_1.services.$q.reject(reason), { reason: reason }); + }; + RejectFactory.prototype.redirected = function (detail) { + return this.superseded(detail, { redirected: true }); + }; + RejectFactory.prototype.invalid = function (detail) { + var message = "This transition is invalid (see detail)"; + var reason = new TransitionRejection(RejectType.INVALID, message, detail); + return common_1.extend(coreservices_1.services.$q.reject(reason), { reason: reason }); + }; + RejectFactory.prototype.ignored = function (detail) { + var message = "The transition was ignored."; + var reason = new TransitionRejection(RejectType.IGNORED, message, detail); + return common_1.extend(coreservices_1.services.$q.reject(reason), { reason: reason }); + }; + RejectFactory.prototype.aborted = function (detail) { + // TODO think about how to encapsulate an Error() object + var message = "The transition has been aborted."; + var reason = new TransitionRejection(RejectType.ABORTED, message, detail); + return common_1.extend(coreservices_1.services.$q.reject(reason), { reason: reason }); + }; + return RejectFactory; + }()); + exports.RejectFactory = RejectFactory; + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module transition */ /** for typedoc */ + var trace_1 = __webpack_require__(12); + var coreservices_1 = __webpack_require__(6); + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var hof_1 = __webpack_require__(5); + var module_1 = __webpack_require__(13); + var node_1 = __webpack_require__(39); + var pathFactory_1 = __webpack_require__(38); + var module_2 = __webpack_require__(17); + var module_3 = __webpack_require__(20); + var module_4 = __webpack_require__(40); + var transitionCount = 0, REJECT = new module_1.RejectFactory(); + var stateSelf = hof_1.prop("self"); + /** + * The representation of a transition between two states. + * + * Contains all contextual information about the to/from states, parameters, resolves, as well as the + * list of states being entered and exited as a result of this transition. + */ + var Transition = (function () { + /** + * Creates a new Transition object. + * + * If the target state is not valid, an error is thrown. + * + * @param fromPath The path of [[Node]]s from which the transition is leaving. The last node in the `fromPath` + * encapsulates the "from state". + * @param targetState The target state and parameters being transitioned to (also, the transition options) + * @param _transitionService The Transition Service instance + */ + function Transition(fromPath, targetState, _transitionService) { + var _this = this; + this._transitionService = _transitionService; + this._deferred = coreservices_1.services.$q.defer(); + /** + * This promise is resolved or rejected based on the outcome of the Transition. + * + * When the transition is successful, the promise is resolved + * When the transition is unsuccessful, the promise is rejected with the [[TransitionRejection]] or javascript error + */ + this.promise = this._deferred.promise; + this.treeChanges = function () { return _this._treeChanges; }; + this.isActive = function () { return _this === _this._options.current(); }; + if (!targetState.valid()) { + throw new Error(targetState.error()); + } + // Makes the Transition instance a hook registry (onStart, etc) + module_1.HookRegistry.mixin(new module_1.HookRegistry(), this); + // current() is assumed to come from targetState.options, but provide a naive implementation otherwise. + this._options = common_1.extend({ current: hof_1.val(this) }, targetState.options()); + this.$id = transitionCount++; + var toPath = pathFactory_1.PathFactory.buildToPath(fromPath, targetState); + toPath = pathFactory_1.PathFactory.applyViewConfigs(_transitionService.$view, toPath); + this._treeChanges = pathFactory_1.PathFactory.treeChanges(fromPath, toPath, this._options.reloadState); + pathFactory_1.PathFactory.bindTransitionResolve(this._treeChanges, this); + } + Transition.prototype.$from = function () { + return common_1.tail(this._treeChanges.from).state; + }; + Transition.prototype.$to = function () { + return common_1.tail(this._treeChanges.to).state; + }; + /** + * Returns the "from state" + * + * @returns The state object for the Transition's "from state". + */ + Transition.prototype.from = function () { + return this.$from().self; + }; + /** + * Returns the "to state" + * + * @returns The state object for the Transition's target state ("to state"). + */ + Transition.prototype.to = function () { + return this.$to().self; + }; + /** + * Determines whether two transitions are equivalent. + */ + Transition.prototype.is = function (compare) { + if (compare instanceof Transition) { + // TODO: Also compare parameters + return this.is({ to: compare.$to().name, from: compare.$from().name }); + } + return !((compare.to && !module_1.matchState(this.$to(), compare.to)) || + (compare.from && !module_1.matchState(this.$from(), compare.from))); + }; + /** + * Gets transition parameter values + * + * @param pathname Pick which treeChanges path to get parameters for: + * (`'to'`, `'from'`, `'entering'`, `'exiting'`, `'retained'`) + * @returns transition parameter values for the desired path. + */ + Transition.prototype.params = function (pathname) { + if (pathname === void 0) { pathname = "to"; } + return this._treeChanges[pathname].map(hof_1.prop("paramValues")).reduce(common_1.mergeR, {}); + }; + /** + * Get resolved data + * + * @returns an object (key/value pairs) where keys are resolve names and values are any settled resolve data, + * or `undefined` for pending resolve data + */ + Transition.prototype.resolves = function () { + return common_1.map(common_1.tail(this._treeChanges.to).resolveContext.getResolvables(), function (res) { return res.data; }); + }; + /** + * Adds new resolves to this transition. + * + * @param resolves an [[ResolveDeclarations]] object which describes the new resolves + * @param state the state in the "to path" which should receive the new resolves (otherwise, the root state) + */ + Transition.prototype.addResolves = function (resolves, state) { + if (state === void 0) { state = ""; } + var stateName = (typeof state === "string") ? state : state.name; + var topath = this._treeChanges.to; + var targetNode = common_1.find(topath, function (node) { return node.state.name === stateName; }); + common_1.tail(topath).resolveContext.addResolvables(module_4.Resolvable.makeResolvables(resolves), targetNode.state); + }; + /** + * Gets the previous transition, from which this transition was redirected. + * + * @returns The previous Transition, or null if this Transition is not the result of a redirection + */ + Transition.prototype.previous = function () { + return this._options.previous || null; + }; + /** + * Get the transition options + * + * @returns the options for this Transition. + */ + Transition.prototype.options = function () { + return this._options; + }; + /** + * Gets the states being entered. + * + * @returns an array of states that will be entered during this transition. + */ + Transition.prototype.entering = function () { + return common_1.map(this._treeChanges.entering, hof_1.prop('state')).map(stateSelf); + }; + /** + * Gets the states being exited. + * + * @returns an array of states that will be exited during this transition. + */ + Transition.prototype.exiting = function () { + return common_1.map(this._treeChanges.exiting, hof_1.prop('state')).map(stateSelf).reverse(); + }; + /** + * Gets the states being retained. + * + * @returns an array of states that are already entered from a previous Transition, that will not be + * exited during this Transition + */ + Transition.prototype.retained = function () { + return common_1.map(this._treeChanges.retained, hof_1.prop('state')).map(stateSelf); + }; + /** + * Get the [[ViewConfig]]s associated with this Transition + * + * Each state can define one or more views (template/controller), which are encapsulated as `ViewConfig` objects. + * This method fetches the `ViewConfigs` for a given path in the Transition (e.g., "to" or "entering"). + * + * @param pathname the name of the path to fetch views for: + * (`'to'`, `'from'`, `'entering'`, `'exiting'`, `'retained'`) + * @param state If provided, only returns the `ViewConfig`s for a single state in the path + * + * @returns a list of ViewConfig objects for the given path. + */ + Transition.prototype.views = function (pathname, state) { + if (pathname === void 0) { pathname = "entering"; } + var path = this._treeChanges[pathname]; + path = !state ? path : path.filter(hof_1.propEq('state', state)); + return path.map(hof_1.prop("views")).filter(common_1.identity).reduce(common_1.unnestR, []); + }; + /** + * @ngdoc function + * @name ui.router.state.type:Transition#redirect + * @methodOf ui.router.state.type:Transition + * + * @description + * Creates a new transition that is a redirection of the current one. This transition can + * be returned from a `$transitionsProvider` hook, `$state` event, or other method, to + * redirect a transition to a new state and/or set of parameters. + * + * @returns {Transition} Returns a new `Transition` instance. + */ + Transition.prototype.redirect = function (targetState) { + var newOptions = common_1.extend({}, this.options(), targetState.options(), { previous: this }); + targetState = new module_2.TargetState(targetState.identifier(), targetState.$state(), targetState.params(), newOptions); + var redirectTo = new Transition(this._treeChanges.from, targetState, this._transitionService); + var reloadState = targetState.options().reloadState; + // If the current transition has already resolved any resolvables which are also in the redirected "to path", then + // add those resolvables to the redirected transition. Allows you to define a resolve at a parent level, wait for + // the resolve, then redirect to a child state based on the result, and not have to re-fetch the resolve. + var redirectedPath = this.treeChanges().to; + var copyResolvesFor = node_1.Node.matching(redirectTo.treeChanges().to, redirectedPath) + .filter(function (node) { return !reloadState || !reloadState.includes[node.state.name]; }); + var includeResolve = function (resolve, key) { return ['$stateParams', '$transition$'].indexOf(key) === -1; }; + copyResolvesFor.forEach(function (node, idx) { return common_1.extend(node.resolves, common_1.filter(redirectedPath[idx].resolves, includeResolve)); }); + return redirectTo; + }; + /** @hidden If a transition doesn't exit/enter any states, returns any [[Param]] whose value changed */ + Transition.prototype._changedParams = function () { + var _a = this._treeChanges, to = _a.to, from = _a.from; + if (this._options.reload || common_1.tail(to).state !== common_1.tail(from).state) + return undefined; + var nodeSchemas = to.map(function (node) { return node.paramSchema; }); + var _b = [to, from].map(function (path) { return path.map(function (x) { return x.paramValues; }); }), toValues = _b[0], fromValues = _b[1]; + var tuples = common_1.arrayTuples(nodeSchemas, toValues, fromValues); + return tuples.map(function (_a) { + var schema = _a[0], toVals = _a[1], fromVals = _a[2]; + return module_3.Param.changed(schema, toVals, fromVals); + }).reduce(common_1.unnestR, []); + }; + /** + * Returns true if the transition is dynamic. + * + * A transition is dynamic if no states are entered nor exited, but at least one dynamic parameter has changed. + * + * @returns true if the Transition is dynamic + */ + Transition.prototype.dynamic = function () { + var changes = this._changedParams(); + return !changes ? false : changes.map(function (x) { return x.dynamic; }).reduce(common_1.anyTrueR, false); + }; + /** + * Returns true if the transition is ignored. + * + * A transition is ignored if no states are entered nor exited, and no parameter values have changed. + * + * @returns true if the Transition is ignored. + */ + Transition.prototype.ignored = function () { + var changes = this._changedParams(); + return !changes ? false : changes.length === 0; + }; + /** + * @hidden + */ + Transition.prototype.hookBuilder = function () { + return new module_1.HookBuilder(this._transitionService, this, { + transition: this, + current: this._options.current + }); + }; + /** + * Runs the transition + * + * This method is generally called from the [[StateService.transitionTo]] + * + * @returns a promise for a successful transition. + */ + Transition.prototype.run = function () { + var _this = this; + var hookBuilder = this.hookBuilder(); + var runSynchronousHooks = module_1.TransitionHook.runSynchronousHooks; + // TODO: nuke these in favor of chaining off the promise, i.e., + // $transitions.onBefore({}, $transition$ => {$transition$.promise.then()} + var runSuccessHooks = function () { return runSynchronousHooks(hookBuilder.getOnSuccessHooks(), {}, true); }; + var runErrorHooks = function ($error$) { return runSynchronousHooks(hookBuilder.getOnErrorHooks(), { $error$: $error$ }, true); }; + // Run the success/error hooks *after* the Transition promise is settled. + this.promise.then(runSuccessHooks, runErrorHooks); + var syncResult = runSynchronousHooks(hookBuilder.getOnBeforeHooks()); + if (module_1.TransitionHook.isRejection(syncResult)) { + var rejectReason = syncResult.reason; + this._deferred.reject(rejectReason); + return this.promise; + } + if (!this.valid()) { + var error = new Error(this.error()); + this._deferred.reject(error); + return this.promise; + } + if (this.ignored()) { + trace_1.trace.traceTransitionIgnored(this); + var ignored = REJECT.ignored(); + this._deferred.reject(ignored.reason); + return this.promise; + } + // When the chain is complete, then resolve or reject the deferred + var resolve = function () { + _this.success = true; + _this._deferred.resolve(_this); + trace_1.trace.traceSuccess(_this.$to(), _this); + }; + var reject = function (error) { + _this.success = false; + _this._deferred.reject(error); + trace_1.trace.traceError(error, _this); + return coreservices_1.services.$q.reject(error); + }; + trace_1.trace.traceTransitionStart(this); + var chain = hookBuilder.asyncHooks().reduce(function (_chain, step) { return _chain.then(step.invokeStep); }, syncResult); + chain.then(resolve, reject); + return this.promise; + }; + /** + * Checks if the Transition is valid + * + * @returns true if the Transition is valid + */ + Transition.prototype.valid = function () { + return !this.error(); + }; + /** + * The reason the Transition is invalid + * + * @returns an error message explaining why the transition is invalid + */ + Transition.prototype.error = function () { + var state = this.$to(); + if (state.self[common_1.abstractKey]) + return "Cannot transition to abstract state '" + state.name + "'"; + if (!module_3.Param.validates(state.parameters(), this.params())) + return "Param values not valid for state '" + state.name + "'"; + }; + /** + * A string representation of the Transition + * + * @returns A string representation of the Transition + */ + Transition.prototype.toString = function () { + var fromStateOrName = this.from(); + var toStateOrName = this.to(); + var avoidEmptyHash = function (params) { + return (params["#"] !== null && params["#"] !== undefined) ? params : common_1.omit(params, "#"); + }; + // (X) means the to state is invalid. + var id = this.$id, from = predicates_1.isObject(fromStateOrName) ? fromStateOrName.name : fromStateOrName, fromParams = common_1.toJson(avoidEmptyHash(this._treeChanges.from.map(hof_1.prop('paramValues')).reduce(common_1.mergeR, {}))), toValid = this.valid() ? "" : "(X) ", to = predicates_1.isObject(toStateOrName) ? toStateOrName.name : toStateOrName, toParams = common_1.toJson(avoidEmptyHash(this.params())); + return "Transition#" + id + "( '" + from + "'" + fromParams + " -> " + toValid + "'" + to + "'" + toParams + " )"; + }; + return Transition; + }()); + exports.Transition = Transition; + + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** + * UI-Router Transition Tracing + * + * Enable transition tracing to print transition information to the console, in order to help debug your application. + * Tracing logs detailed information about each Transition to your console. + * + * To enable tracing, import the [[trace]] singleton and enable one or more categories. + * + * ES6 + * ``` + * + * import {trace} from "ui-router-ng2"; // or "angular-ui-router" + * trace.enable(1, 5); // TRANSITION and VIEWCONFIG + * ``` + * + * CJS + * ``` + * + * let trace = require("angular-ui-router").trace; // or "ui-router-ng2" + * trace.enable("TRANSITION", "VIEWCONFIG"); + * ``` + * + * Globals + * ``` + * + * let trace = window["angular-ui-router"].trace; // or "ui-router-ng2" + * trace.enable(); // Trace everything (very verbose) + * ``` + * + * @module trace + */ /** for typedoc */ + var hof_1 = __webpack_require__(5); + var predicates_1 = __webpack_require__(4); + var strings_1 = __webpack_require__(9); + /** @hidden */ + function uiViewString(viewData) { + if (!viewData) + return 'ui-view (defunct)'; + return "ui-view id#" + viewData.id + ", contextual name '" + viewData.name + "@" + viewData.creationContext + "', fqn: '" + viewData.fqn + "'"; + } + /** @hidden */ + var viewConfigString = function (viewConfig) { + return ("ViewConfig targeting ui-view: '" + viewConfig.viewDecl.$uiViewName + "@" + viewConfig.viewDecl.$uiViewContextAnchor + "', context: '" + viewConfig.viewDecl.$context.name + "'"); + }; + /** @hidden */ + function normalizedCat(input) { + return predicates_1.isNumber(input) ? Category[input] : Category[Category[input]]; + } + /** + * Trace categories + * + * [[Trace.enable]] or [[Trace.disable]] a category + * + * `trace.enable(Category.TRANSITION)` + * + * These can also be provided using a matching string, or position ordinal + * + * `trace.enable("TRANSITION")` + * + * `trace.enable(1)` + */ + (function (Category) { + Category[Category["RESOLVE"] = 0] = "RESOLVE"; + Category[Category["TRANSITION"] = 1] = "TRANSITION"; + Category[Category["HOOK"] = 2] = "HOOK"; + Category[Category["INVOKE"] = 3] = "INVOKE"; + Category[Category["UIVIEW"] = 4] = "UIVIEW"; + Category[Category["VIEWCONFIG"] = 5] = "VIEWCONFIG"; + })(exports.Category || (exports.Category = {})); + var Category = exports.Category; + /** + * Prints UI-Router Transition trace information to the console. + */ + var Trace = (function () { + function Trace() { + /** @hidden */ + this._enabled = {}; + this.approximateDigests = 0; + } + /** @hidden */ + Trace.prototype._set = function (enabled, categories) { + var _this = this; + if (!categories.length) { + categories = Object.keys(Category) + .filter(function (k) { return isNaN(parseInt(k, 10)); }) + .map(function (key) { return Category[key]; }); + } + categories.map(normalizedCat).forEach(function (category) { return _this._enabled[category] = enabled; }); + }; + /** + * Enables a trace [[Category]] + * + * ``` + * trace.enable("TRANSITION"); + * ``` + * + * @param categories categories to enable. If `categories` is omitted, all categories are enabled. + * Also takes strings (category name) or ordinal (category position) + */ + Trace.prototype.enable = function () { + var categories = []; + for (var _i = 0; _i < arguments.length; _i++) { + categories[_i - 0] = arguments[_i]; + } + this._set(true, categories); + }; + /** + * Disables a trace [[Category]] + * + * ``` + * trace.disable("VIEWCONFIG"); + * ``` + * + * @param categories categories to disable. If `categories` is omitted, all categories are disabled. + * Also takes strings (category name) or ordinal (category position) + */ + Trace.prototype.disable = function () { + var categories = []; + for (var _i = 0; _i < arguments.length; _i++) { + categories[_i - 0] = arguments[_i]; + } + this._set(false, categories); + }; + /** + * Retrieves the enabled stateus of a [[Category]] + * + * ``` + * trace.enabled("VIEWCONFIG"); // true or false + * ``` + * + * @returns boolean true if the category is enabled + */ + Trace.prototype.enabled = function (category) { + return !!this._enabled[normalizedCat(category)]; + }; + /** called by ui-router code */ + Trace.prototype.traceTransitionStart = function (transition) { + if (!this.enabled(Category.TRANSITION)) + return; + var tid = transition.$id, digest = this.approximateDigests, transitionStr = strings_1.stringify(transition); + console.log("Transition #" + tid + " Digest #" + digest + ": Started -> " + transitionStr); + }; + /** called by ui-router code */ + Trace.prototype.traceTransitionIgnored = function (transition) { + if (!this.enabled(Category.TRANSITION)) + return; + var tid = transition.$id, digest = this.approximateDigests, transitionStr = strings_1.stringify(transition); + console.log("Transition #" + tid + " Digest #" + digest + ": Ignored <> " + transitionStr); + }; + /** called by ui-router code */ + Trace.prototype.traceHookInvocation = function (step, options) { + if (!this.enabled(Category.HOOK)) + return; + var tid = hof_1.parse("transition.$id")(options), digest = this.approximateDigests, event = hof_1.parse("traceData.hookType")(options) || "internal", context = hof_1.parse("traceData.context.state.name")(options) || hof_1.parse("traceData.context")(options) || "unknown", name = strings_1.functionToString(step.fn); + console.log("Transition #" + tid + " Digest #" + digest + ": Hook -> " + event + " context: " + context + ", " + strings_1.maxLength(200, name)); + }; + /** called by ui-router code */ + Trace.prototype.traceHookResult = function (hookResult, transitionResult, transitionOptions) { + if (!this.enabled(Category.HOOK)) + return; + var tid = hof_1.parse("transition.$id")(transitionOptions), digest = this.approximateDigests, hookResultStr = strings_1.stringify(hookResult), transitionResultStr = strings_1.stringify(transitionResult); + console.log("Transition #" + tid + " Digest #" + digest + ": <- Hook returned: " + strings_1.maxLength(200, hookResultStr) + ", transition result: " + strings_1.maxLength(200, transitionResultStr)); + }; + /** called by ui-router code */ + Trace.prototype.traceResolvePath = function (path, options) { + if (!this.enabled(Category.RESOLVE)) + return; + var tid = hof_1.parse("transition.$id")(options), digest = this.approximateDigests, pathStr = path && path.toString(), policyStr = options && options.resolvePolicy; + console.log("Transition #" + tid + " Digest #" + digest + ": Resolving " + pathStr + " (" + policyStr + ")"); + }; + /** called by ui-router code */ + Trace.prototype.traceResolvePathElement = function (pathElement, resolvablePromises, options) { + if (!this.enabled(Category.RESOLVE)) + return; + if (!resolvablePromises.length) + return; + var tid = hof_1.parse("transition.$id")(options), digest = this.approximateDigests, resolvablePromisesStr = Object.keys(resolvablePromises).join(", "), pathElementStr = pathElement && pathElement.toString(), policyStr = options && options.resolvePolicy; + console.log("Transition #" + tid + " Digest #" + digest + ": Resolve " + pathElementStr + " resolvables: [" + resolvablePromisesStr + "] (" + policyStr + ")"); + }; + /** called by ui-router code */ + Trace.prototype.traceResolveResolvable = function (resolvable, options) { + if (!this.enabled(Category.RESOLVE)) + return; + var tid = hof_1.parse("transition.$id")(options), digest = this.approximateDigests, resolvableStr = resolvable && resolvable.toString(); + console.log("Transition #" + tid + " Digest #" + digest + ": Resolving -> " + resolvableStr); + }; + /** called by ui-router code */ + Trace.prototype.traceResolvableResolved = function (resolvable, options) { + if (!this.enabled(Category.RESOLVE)) + return; + var tid = hof_1.parse("transition.$id")(options), digest = this.approximateDigests, resolvableStr = resolvable && resolvable.toString(), result = strings_1.stringify(resolvable.data); + console.log("Transition #" + tid + " Digest #" + digest + ": <- Resolved " + resolvableStr + " to: " + strings_1.maxLength(200, result)); + }; + /** called by ui-router code */ + Trace.prototype.tracePathElementInvoke = function (node, fn, deps, options) { + if (!this.enabled(Category.INVOKE)) + return; + var tid = hof_1.parse("transition.$id")(options), digest = this.approximateDigests, stateName = node && node.state && node.state.toString(), fnName = strings_1.functionToString(fn); + console.log("Transition #" + tid + " Digest #" + digest + ": Invoke " + options.when + ": context: " + stateName + " " + strings_1.maxLength(200, fnName)); + }; + /** called by ui-router code */ + Trace.prototype.traceError = function (error, transition) { + if (!this.enabled(Category.TRANSITION)) + return; + var tid = transition.$id, digest = this.approximateDigests, transitionStr = strings_1.stringify(transition); + console.log("Transition #" + tid + " Digest #" + digest + ": <- Rejected " + transitionStr + ", reason: " + error); + }; + /** called by ui-router code */ + Trace.prototype.traceSuccess = function (finalState, transition) { + if (!this.enabled(Category.TRANSITION)) + return; + var tid = transition.$id, digest = this.approximateDigests, state = finalState.name, transitionStr = strings_1.stringify(transition); + console.log("Transition #" + tid + " Digest #" + digest + ": <- Success " + transitionStr + ", final state: " + state); + }; + /** called by ui-router code */ + Trace.prototype.traceUiViewEvent = function (event, viewData, extra) { + if (extra === void 0) { extra = ""; } + if (!this.enabled(Category.UIVIEW)) + return; + console.log("ui-view: " + strings_1.padString(30, event) + " " + uiViewString(viewData) + extra); + }; + /** called by ui-router code */ + Trace.prototype.traceUiViewConfigUpdated = function (viewData, context) { + if (!this.enabled(Category.UIVIEW)) + return; + this.traceUiViewEvent("Updating", viewData, " with ViewConfig from context='" + context + "'"); + }; + /** called by ui-router code */ + Trace.prototype.traceUiViewScopeCreated = function (viewData, newScope) { + if (!this.enabled(Category.UIVIEW)) + return; + this.traceUiViewEvent("Created scope for", viewData, ", scope #" + newScope.$id); + }; + /** called by ui-router code */ + Trace.prototype.traceUiViewFill = function (viewData, html) { + if (!this.enabled(Category.UIVIEW)) + return; + this.traceUiViewEvent("Fill", viewData, " with: " + strings_1.maxLength(200, html)); + }; + /** called by ui-router code */ + Trace.prototype.traceViewServiceEvent = function (event, viewConfig) { + if (!this.enabled(Category.VIEWCONFIG)) + return; + console.log("$view.ViewConfig: " + event + " " + viewConfigString(viewConfig)); + }; + /** called by ui-router code */ + Trace.prototype.traceViewServiceUiViewEvent = function (event, viewData) { + if (!this.enabled(Category.VIEWCONFIG)) + return; + console.log("$view.ViewConfig: " + event + " " + uiViewString(viewData)); + }; + return Trace; + }()); + exports.Trace = Trace; + /** + * The [[Trace]] singleton + * + * @example + * ```js + * + * import {trace} from "angular-ui-router"; + * trace.enable(1, 5); + * ``` + */ + var trace = new Trace(); + exports.trace = trace; + + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** + * This module contains APIs related to a Transition. + * + * See [[Transition]], [[$transitions]] + * + * @module transition + * @preferred + */ + /** for typedoc */ + __export(__webpack_require__(14)); + __export(__webpack_require__(15)); + __export(__webpack_require__(10)); + __export(__webpack_require__(11)); + __export(__webpack_require__(16)); + __export(__webpack_require__(43)); + + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module transition */ /** for typedoc */ + "use strict"; + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var module_1 = __webpack_require__(13); + /** + * This class returns applicable TransitionHooks for a specific Transition instance. + * + * Hooks (IEventHook) may be registered globally, e.g., $transitions.onEnter(...), or locally, e.g. + * myTransition.onEnter(...). The HookBuilder finds matching IEventHooks (where the match criteria is + * determined by the type of hook) + * + * The HookBuilder also converts IEventHooks objects to TransitionHook objects, which are used to run a Transition. + * + * The HookBuilder constructor is given the $transitions service and a Transition instance. Thus, a HookBuilder + * instance may only be used for one specific Transition object. (side note: the _treeChanges accessor is private + * in the Transition class, so we must also provide the Transition's _treeChanges) + * + */ + var HookBuilder = (function () { + function HookBuilder($transitions, transition, baseHookOptions) { + var _this = this; + this.$transitions = $transitions; + this.transition = transition; + this.baseHookOptions = baseHookOptions; + // TODO: These get* methods are returning different cardinalities of hooks + // onBefore/onStart/onFinish/onSuccess/onError returns an array of hooks + // onExit/onRetain/onEnter returns an array of arrays of hooks + this.getOnBeforeHooks = function () { return _this._buildNodeHooks("onBefore", "to", tupleSort(), undefined, { async: false }); }; + this.getOnStartHooks = function () { return _this._buildNodeHooks("onStart", "to", tupleSort()); }; + this.getOnExitHooks = function () { return _this._buildNodeHooks("onExit", "exiting", tupleSort(true), function (node) { return ({ $state$: node.state }); }); }; + this.getOnRetainHooks = function () { return _this._buildNodeHooks("onRetain", "retained", tupleSort(), function (node) { return ({ $state$: node.state }); }); }; + this.getOnEnterHooks = function () { return _this._buildNodeHooks("onEnter", "entering", tupleSort(), function (node) { return ({ $state$: node.state }); }); }; + this.getOnFinishHooks = function () { return _this._buildNodeHooks("onFinish", "to", tupleSort(), function (node) { return ({ $treeChanges$: _this.treeChanges }); }); }; + this.getOnSuccessHooks = function () { return _this._buildNodeHooks("onSuccess", "to", tupleSort(), undefined, { async: false, rejectIfSuperseded: false }); }; + this.getOnErrorHooks = function () { return _this._buildNodeHooks("onError", "to", tupleSort(), undefined, { async: false, rejectIfSuperseded: false }); }; + this.treeChanges = transition.treeChanges(); + this.toState = common_1.tail(this.treeChanges.to).state; + this.fromState = common_1.tail(this.treeChanges.from).state; + this.transitionOptions = transition.options(); + } + HookBuilder.prototype.asyncHooks = function () { + var onStartHooks = this.getOnStartHooks(); + var onExitHooks = this.getOnExitHooks(); + var onRetainHooks = this.getOnRetainHooks(); + var onEnterHooks = this.getOnEnterHooks(); + var onFinishHooks = this.getOnFinishHooks(); + var asyncHooks = [onStartHooks, onExitHooks, onRetainHooks, onEnterHooks, onFinishHooks]; + return asyncHooks.reduce(common_1.unnestR, []).filter(common_1.identity); + }; + /** + * Returns an array of newly built TransitionHook objects. + * + * - Finds all IEventHooks registered for the given `hookType` which matched the transition's [[TreeChanges]]. + * - Finds [[Node]] (or `Node[]`) to use as the TransitionHook context(s) + * - For each of the [[Node]]s, creates a TransitionHook + * + * @param hookType the name of the hook registration function, e.g., 'onEnter', 'onFinish'. + * @param matchingNodesProp selects which [[Node]]s from the [[IMatchingNodes]] object to create hooks for. + * @param getLocals a function which accepts a [[Node]] and returns additional locals to provide to the hook as injectables + * @param sortHooksFn a function which compares two HookTuple and returns <1, 0, or >1 + * @param options any specific Transition Hook Options + */ + HookBuilder.prototype._buildNodeHooks = function (hookType, matchingNodesProp, sortHooksFn, getLocals, options) { + var _this = this; + if (getLocals === void 0) { getLocals = function (node) { return ({}); }; } + // Find all the matching registered hooks for a given hook type + var matchingHooks = this._matchingHooks(hookType, this.treeChanges); + if (!matchingHooks) + return []; + var makeTransitionHooks = function (hook) { + // Fetch the Nodes that caused this hook to match. + var matches = hook.matches(_this.treeChanges); + // Select the Node[] that will be used as TransitionHook context objects + var nodes = matches[matchingNodesProp]; + // Return an array of HookTuples + return nodes.map(function (node) { + var _options = common_1.extend({ bind: hook.bind, traceData: { hookType: hookType, context: node } }, _this.baseHookOptions, options); + var transitionHook = new module_1.TransitionHook(hook.callback, getLocals(node), node.resolveContext, _options); + return { hook: hook, node: node, transitionHook: transitionHook }; + }); + }; + return matchingHooks.map(makeTransitionHooks) + .reduce(common_1.unnestR, []) + .sort(sortHooksFn) + .map(function (tuple) { return tuple.transitionHook; }); + }; + /** + * Finds all IEventHooks from: + * - The Transition object instance hook registry + * - The TransitionService ($transitions) global hook registry + * + * which matched: + * - the eventType + * - the matchCriteria (to, from, exiting, retained, entering) + * + * @returns an array of matched [[IEventHook]]s + */ + HookBuilder.prototype._matchingHooks = function (hookName, treeChanges) { + return [this.transition, this.$transitions] // Instance and Global hook registries + .map(function (reg) { return reg.getHooks(hookName); }) // Get named hooks from registries + .filter(common_1.assertPredicate(predicates_1.isArray, "broken event named: " + hookName)) // Sanity check + .reduce(common_1.unnestR, []) // Un-nest IEventHook[][] to IEventHook[] array + .filter(function (hook) { return hook.matches(treeChanges); }); // Only those satisfying matchCriteria + }; + return HookBuilder; + }()); + exports.HookBuilder = HookBuilder; + /** + * A factory for a sort function for HookTuples. + * + * The sort function first compares the Node depth (how deep in the state tree a node is), then compares + * the EventHook priority. + * + * @param reverseDepthSort a boolean, when true, reverses the sort order for the node depth + * @returns a tuple sort function + */ + function tupleSort(reverseDepthSort) { + if (reverseDepthSort === void 0) { reverseDepthSort = false; } + return function nodeDepthThenPriority(l, r) { + var factor = reverseDepthSort ? -1 : 1; + var depthDelta = (l.node.state.path.length - r.node.state.path.length) * factor; + return depthDelta !== 0 ? depthDelta : r.hook.priority - l.hook.priority; + }; + } + + +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module transition */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var glob_1 = __webpack_require__(7); + /** + * Determines if the given state matches the matchCriteria + * @param state a State Object to test against + * @param criterion + * - If a string, matchState uses the string as a glob-matcher against the state name + * - If an array (of strings), matchState uses each string in the array as a glob-matchers against the state name + * and returns a positive match if any of the globs match. + * - If a function, matchState calls the function with the state and returns true if the function's result is truthy. + * @returns {boolean} + */ + function matchState(state, criterion) { + var toMatch = predicates_1.isString(criterion) ? [criterion] : criterion; + function matchGlobs(_state) { + var globStrings = toMatch; + for (var i = 0; i < globStrings.length; i++) { + var glob = glob_1.Glob.fromString(globStrings[i]); + if ((glob && glob.matches(_state.name)) || (!glob && globStrings[i] === _state.name)) { + return true; + } + } + return false; + } + var matchFn = (predicates_1.isFunction(toMatch) ? toMatch : matchGlobs); + return !!matchFn(state); + } + exports.matchState = matchState; + var EventHook = (function () { + function EventHook(matchCriteria, callback, options) { + if (options === void 0) { options = {}; } + this.callback = callback; + this.matchCriteria = common_1.extend({ to: true, from: true, exiting: true, retained: true, entering: true }, matchCriteria); + this.priority = options.priority || 0; + this.bind = options.bind || null; + } + EventHook._matchingNodes = function (nodes, criterion) { + if (criterion === true) + return nodes; + var matching = nodes.filter(function (node) { return matchState(node.state, criterion); }); + return matching.length ? matching : null; + }; + /** + * Determines if this hook's [[matchCriteria]] match the given [[TreeChanges]] + * + * @returns an IMatchingNodes object, or null. If an IMatchingNodes object is returned, its values + * are the matching [[Node]]s for each [[HookMatchCriterion]] (to, from, exiting, retained, entering) + */ + EventHook.prototype.matches = function (treeChanges) { + var mc = this.matchCriteria, _matchingNodes = EventHook._matchingNodes; + var matches = { + to: _matchingNodes([common_1.tail(treeChanges.to)], mc.to), + from: _matchingNodes([common_1.tail(treeChanges.from)], mc.from), + exiting: _matchingNodes(treeChanges.exiting, mc.exiting), + retained: _matchingNodes(treeChanges.retained, mc.retained), + entering: _matchingNodes(treeChanges.entering, mc.entering), + }; + // Check if all the criteria matched the TreeChanges object + var allMatched = ["to", "from", "exiting", "retained", "entering"] + .map(function (prop) { return matches[prop]; }) + .reduce(common_1.allTrueR, true); + return allMatched ? matches : null; + }; + return EventHook; + }()); + exports.EventHook = EventHook; + // Return a registration function of the requested type. + function makeHookRegistrationFn(hooks, name) { + return function (matchObject, callback, options) { + if (options === void 0) { options = {}; } + var eventHook = new EventHook(matchObject, callback, options); + hooks[name].push(eventHook); + return function deregisterEventHook() { + common_1.removeFrom(hooks[name])(eventHook); + }; + }; + } + var HookRegistry = (function () { + function HookRegistry() { + var _this = this; + this._transitionEvents = { + onBefore: [], onStart: [], onEnter: [], onRetain: [], onExit: [], onFinish: [], onSuccess: [], onError: [] + }; + this.getHooks = function (name) { return _this._transitionEvents[name]; }; + this.onBefore = makeHookRegistrationFn(this._transitionEvents, "onBefore"); + this.onStart = makeHookRegistrationFn(this._transitionEvents, "onStart"); + /** + * @ngdoc function + * @name ui.router.state.$transitionsProvider#onEnter + * @methodOf ui.router.state.$transitionsProvider + * + * @description + * Registers a function to be injected and invoked during a transition between the matched 'to' and 'from' states, + * when the matched 'to' state is being entered. This function is injected with the entering state's resolves. + * + * This function can be injected with two additional special value: + * - **`$transition$`**: The current transition + * - **`$state$`**: The state being entered + * + * @param {object} matchObject See transitionCriteria in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + * @param {function} callback See callback in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + */ + this.onEnter = makeHookRegistrationFn(this._transitionEvents, "onEnter"); + /** + * @ngdoc function + * @name ui.router.state.$transitionsProvider#onRetain + * @methodOf ui.router.state.$transitionsProvider + * + * @description + * Registers a function to be injected and invoked during a transition between the matched 'to' and 'from states, + * when the matched 'from' state is already active and is not being exited nor entered. + * + * This function can be injected with two additional special value: + * - **`$transition$`**: The current transition + * - **`$state$`**: The state that is retained + * + * @param {object} matchObject See transitionCriteria in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + * @param {function} callback See callback in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + */ + this.onRetain = makeHookRegistrationFn(this._transitionEvents, "onRetain"); + /** + * @ngdoc function + * @name ui.router.state.$transitionsProvider#onExit + * @methodOf ui.router.state.$transitionsProvider + * + * @description + * Registers a function to be injected and invoked during a transition between the matched 'to' and 'from states, + * when the matched 'from' state is being exited. This function is in injected with the exiting state's resolves. + * + * This function can be injected with two additional special value: + * - **`$transition$`**: The current transition + * - **`$state$`**: The state being entered + * + * @param {object} matchObject See transitionCriteria in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + * @param {function} callback See callback in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + */ + this.onExit = makeHookRegistrationFn(this._transitionEvents, "onExit"); + /** + * @ngdoc function + * @name ui.router.state.$transitionsProvider#onFinish + * @methodOf ui.router.state.$transitionsProvider + * + * @description + * Registers a function to be injected and invoked when a transition is finished entering/exiting all states. + * + * This function can be injected with: + * - **`$transition$`**: The current transition + * + * @param {object} matchObject See transitionCriteria in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + * @param {function} callback See callback in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + */ + this.onFinish = makeHookRegistrationFn(this._transitionEvents, "onFinish"); + /** + * @ngdoc function + * @name ui.router.state.$transitionsProvider#onSuccess + * @methodOf ui.router.state.$transitionsProvider + * + * @description + * Registers a function to be injected and invoked when a transition has successfully completed between the matched + * 'to' and 'from' state is being exited. + * This function is in injected with the 'to' state's resolves (note: `JIT` resolves are not injected). + * + * This function can be injected with two additional special value: + * - **`$transition$`**: The current transition + * + * @param {object} matchObject See transitionCriteria in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + * @param {function} callback The function which will be injected and invoked, when a matching transition is started. + * The function's return value is ignored. + */ + this.onSuccess = makeHookRegistrationFn(this._transitionEvents, "onSuccess"); + /** + * @ngdoc function + * @name ui.router.state.$transitionsProvider#onError + * @methodOf ui.router.state.$transitionsProvider + * + * @description + * Registers a function to be injected and invoked when a transition has failed for any reason between the matched + * 'to' and 'from' state. The transition rejection reason is injected as `$error$`. + * + * @param {object} matchObject See transitionCriteria in {@link ui.router.state.$transitionsProvider#on $transitionsProvider.on}. + * @param {function} callback The function which will be injected and invoked, when a matching transition is started. + * The function's return value is ignored. + */ + this.onError = makeHookRegistrationFn(this._transitionEvents, "onError"); + } + HookRegistry.mixin = function (source, target) { + Object.keys(source._transitionEvents).concat(["getHooks"]).forEach(function (key) { return target[key] = source[key]; }); + }; + return HookRegistry; + }()); + exports.HookRegistry = HookRegistry; + + +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + var common_1 = __webpack_require__(3); + var strings_1 = __webpack_require__(9); + var predicates_1 = __webpack_require__(4); + var hof_1 = __webpack_require__(5); + var trace_1 = __webpack_require__(12); + var coreservices_1 = __webpack_require__(6); + var rejectFactory_1 = __webpack_require__(10); + var module_1 = __webpack_require__(17); + var REJECT = new rejectFactory_1.RejectFactory(); + var defaultOptions = { + async: true, + rejectIfSuperseded: true, + current: common_1.noop, + transition: null, + traceData: {}, + bind: null + }; + var TransitionHook = (function () { + function TransitionHook(fn, locals, resolveContext, options) { + var _this = this; + this.fn = fn; + this.locals = locals; + this.resolveContext = resolveContext; + this.options = options; + this.isSuperseded = function () { return _this.options.current() !== _this.options.transition; }; + /** + * Handles transition abort and transition redirect. Also adds any returned resolvables + * to the pathContext for the current pathElement. If the transition is rejected, then a rejected + * promise is returned here, otherwise undefined is returned. + */ + this.mapHookResult = hof_1.pattern([ + // Transition is no longer current + [this.isSuperseded, function () { return REJECT.superseded(_this.options.current()); }], + // If the hook returns false, abort the current Transition + [hof_1.eq(false), function () { return REJECT.aborted("Hook aborted transition"); }], + // If the hook returns a Transition, halt the current Transition and redirect to that Transition. + [hof_1.is(module_1.TargetState), function (target) { return REJECT.redirected(target); }], + // A promise was returned, wait for the promise and then chain another hookHandler + [predicates_1.isPromise, function (promise) { return promise.then(_this.handleHookResult.bind(_this)); }] + ]); + this.invokeStep = function (moreLocals) { + var _a = _this, options = _a.options, fn = _a.fn, resolveContext = _a.resolveContext; + var locals = common_1.extend({}, _this.locals, moreLocals); + trace_1.trace.traceHookInvocation(_this, options); + if (options.rejectIfSuperseded && _this.isSuperseded()) { + return REJECT.superseded(options.current()); + } + // TODO: Need better integration of returned promises in synchronous code. + if (!options.async) { + var hookResult = resolveContext.invokeNow(fn, locals, options); + return _this.handleHookResult(hookResult); + } + return resolveContext.invokeLater(fn, locals, options).then(_this.handleHookResult.bind(_this)); + }; + this.options = common_1.defaults(options, defaultOptions); + } + TransitionHook.prototype.handleHookResult = function (hookResult) { + if (!predicates_1.isDefined(hookResult)) + return undefined; + trace_1.trace.traceHookResult(hookResult, undefined, this.options); + var transitionResult = this.mapHookResult(hookResult); + if (transitionResult) + trace_1.trace.traceHookResult(hookResult, transitionResult, this.options); + return transitionResult; + }; + TransitionHook.prototype.toString = function () { + var _a = this, options = _a.options, fn = _a.fn; + var event = hof_1.parse("traceData.hookType")(options) || "internal", context = hof_1.parse("traceData.context.state.name")(options) || hof_1.parse("traceData.context")(options) || "unknown", name = strings_1.fnToString(fn); + return event + " context: " + context + ", " + strings_1.maxLength(200, name); + }; + /** + * Given an array of TransitionHooks, runs each one synchronously and sequentially. + * + * Returns a promise chain composed of any promises returned from each hook.invokeStep() call + */ + TransitionHook.runSynchronousHooks = function (hooks, locals, swallowExceptions) { + if (locals === void 0) { locals = {}; } + if (swallowExceptions === void 0) { swallowExceptions = false; } + var results = []; + for (var i = 0; i < hooks.length; i++) { + try { + results.push(hooks[i].invokeStep(locals)); + } + catch (exception) { + if (!swallowExceptions) + return REJECT.aborted(exception); + console.log("Swallowed exception during synchronous hook handler: " + exception); // TODO: What to do here? + } + } + var rejections = results.filter(TransitionHook.isRejection); + if (rejections.length) + return rejections[0]; + return results + .filter(hof_1.not(TransitionHook.isRejection)) + .filter(predicates_1.isPromise) + .reduce(function (chain, promise) { return chain.then(hof_1.val(promise)); }, coreservices_1.services.$q.when()); + }; + TransitionHook.isRejection = function (hookResult) { + return hookResult && hookResult.reason instanceof rejectFactory_1.TransitionRejection && hookResult; + }; + return TransitionHook; + }()); + exports.TransitionHook = TransitionHook; + + +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** @module state */ /** for typedoc */ + __export(__webpack_require__(18)); + __export(__webpack_require__(19)); + __export(__webpack_require__(26)); + __export(__webpack_require__(33)); + __export(__webpack_require__(34)); + __export(__webpack_require__(35)); + __export(__webpack_require__(36)); + __export(__webpack_require__(37)); + __export(__webpack_require__(27)); + + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** for typedoc */ + var predicates_1 = __webpack_require__(4); + var common_1 = __webpack_require__(3); + /** + * @ngdoc object + * @name ui.router.state.$stateProvider + * + * @requires ui.router.router.$urlRouterProvider + * @requires ui.router.util.$urlMatcherFactoryProvider + * + * @description + * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely + * on state. + * + * A state corresponds to a "place" in the application in terms of the overall UI and + * navigation. A state describes (via the controller / template / view properties) what + * the UI looks like and does at that place. + * + * States often have things in common, and the primary way of factoring out these + * commonalities in this model is via the state hierarchy, i.e. parent/child states aka + * nested states. + * + * The `$stateProvider` provides interfaces to declare these states for your app. + */ + var StateProvider = (function () { + function StateProvider(stateRegistry) { + this.stateRegistry = stateRegistry; + this.invalidCallbacks = []; + common_1.bindFunctions(StateProvider.prototype, this, this); + } + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#decorator + * @methodOf ui.router.state.$stateProvider + * + * @description + * Allows you to extend (carefully) or override (at your own peril) the + * `stateBuilder` object used internally by `$stateProvider`. This can be used + * to add custom functionality to ui-router, for example inferring templateUrl + * based on the state name. + * + * When passing only a name, it returns the current (original or decorated) builder + * function that matches `name`. + * + * The builder functions that can be decorated are listed below. Though not all + * necessarily have a good use case for decoration, that is up to you to decide. + * + * In addition, users can attach custom decorators, which will generate new + * properties within the state's internal definition. There is currently no clear + * use-case for this beyond accessing internal states (i.e. $state.$current), + * however, expect this to become increasingly relevant as we introduce additional + * meta-programming features. + * + * **Warning**: Decorators should not be interdependent because the order of + * execution of the builder functions in non-deterministic. Builder functions + * should only be dependent on the state definition object and super function. + * + * + * Existing builder functions and current return values: + * + * - **parent** `{object}` - returns the parent state object. + * - **data** `{object}` - returns state data, including any inherited data that is not + * overridden by own values (if any). + * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher} + * or `null`. + * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is + * navigable). + * - **params** `{object}` - returns an array of state params that are ensured to + * be a super-set of parent's params. + * - **views** `{object}` - returns a views object where each key is an absolute view + * name (i.e. "viewName@stateName") and each value is the config object + * (template, controller) for the view. Even when you don't use the views object + * explicitly on a state config, one is still created for you internally. + * So by decorating this builder function you have access to decorating template + * and controller properties. + * - **ownParams** `{object}` - returns an array of params that belong to the state, + * not including any params defined by ancestor states. + * - **path** `{string}` - returns the full path from the root down to this state. + * Needed for state activation. + * - **includes** `{object}` - returns an object that includes every state that + * would pass a `$state.includes()` test. + * + * @example + *
+	     * // Override the internal 'views' builder with a function that takes the state
+	     * // definition, and a reference to the internal function being overridden:
+	     * $stateProvider.decorator('views', function (state, parent) {
+	     *   let result = {},
+	     *       views = parent(state);
+	     *
+	     *   angular.forEach(views, function (config, name) {
+	     *     let autoName = (state.name + '.' + name).replace('.', '/');
+	     *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
+	     *     result[name] = config;
+	     *   });
+	     *   return result;
+	     * });
+	     *
+	     * $stateProvider.state('home', {
+	     *   views: {
+	     *     'contact.list': { controller: 'ListController' },
+	     *     'contact.item': { controller: 'ItemController' }
+	     *   }
+	     * });
+	     *
+	     * // ...
+	     *
+	     * $state.go('home');
+	     * // Auto-populates list and item views with /partials/home/contact/list.html,
+	     * // and /partials/home/contact/item.html, respectively.
+	     * 
+ * + * @param {string} name The name of the builder function to decorate. + * @param {object} func A function that is responsible for decorating the original + * builder function. The function receives two parameters: + * + * - `{object}` - state - The state config object. + * - `{object}` - super - The original builder function. + * + * @return {object} $stateProvider - $stateProvider instance + */ + StateProvider.prototype.decorator = function (name, func) { + return this.stateRegistry.decorator(name, func) || this; + }; + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#state + * @methodOf ui.router.state.$stateProvider + * + * @description + * Registers a state configuration under a given state name. The stateConfig object + * has the following acceptable properties. + * + *
+ * + * - **`template`** - {string|function=} - html template as a string or a function that returns + * an html template as a string which should be used by the uiView directives. This property + * takes precedence over templateUrl. + * + * If `template` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + * + * + * - **`templateUrl`** - {string|function=} - path or function that returns a path to an html + * template that should be used by uiView. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + * + * + * - **`templateProvider`** - {function=} - Provider function that returns HTML content + * string. + * + * + * + * - **`controller`** - {string|function=} - Controller fn that should be associated with newly + * related scope or the name of a registered controller if passed as a string. + * + * + * + * - **`controllerProvider`** - {function=} - Injectable provider function that returns + * the actual controller or string. + * + * + * + * - **`controllerAs`** – {string=} – A controller alias name. If present the controller will be + * published to scope under the controllerAs name. + * + * + * + * - **`resolve`** - {object.<string, function>=} - An optional map of dependencies which + * should be injected into the controller. If any of these dependencies are promises, + * the router will wait for them all to be resolved or one to be rejected before the + * controller is instantiated. If all the promises are resolved successfully, the values + * of the resolved promises are injected and $stateChangeSuccess event is fired. If any + * of the promises are rejected the $stateChangeError event is fired. The map object is: + * + * - key - {string}: name of dependency to be injected into controller + * - factory - {string|function}: If string then it is alias for service. Otherwise if function, + * it is injected and return value it treated as dependency. If result is a promise, it is + * resolved before its value is injected into controller. + * + * + * + * - **`url`** - {string=} - A url with optional parameters. When a state is navigated or + * transitioned to, the `$stateParams` service will be populated with any + * parameters that were passed. + * + * + * + * - **`params`** - {object=} - An array of parameter names or regular expressions. Only + * use this within a state if you are not using url. Otherwise you can specify your + * parameters within the url. When a state is navigated or transitioned to, the + * $stateParams service will be populated with any parameters that were passed. + * + * + * + * - **`views`** - {object=} - Use the views property to set up multiple views or to target views + * manually/explicitly. + * + * + * + * - **`abstract`** - {boolean=} - An abstract state will never be directly activated, + * but can provide inherited properties to its common children states. + * + * + * + * - **`onEnter`** - {object=} - Callback function for when a state is entered. Good way + * to trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to use the `['injection1', 'injection2', function(injection1, injection2){}]` syntax. + * + * + * + * - **`onExit`** - {object=} - Callback function for when a state is exited. Good way to + * trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to use the `['injection1', 'injection2', function(injection1, injection2){}]` syntax. + * + * + * + * - **`reloadOnSearch = true`** - {boolean=} - If `false`, will not retrigger the same state + * just because a search/query parameter has changed (via $location.search() or $location.hash()). + * Useful for when you'd like to modify $location.search() without triggering a reload. + * + * + * + * - **`data`** - {object=} - Arbitrary data object, useful for custom configuration. + * + * @example + *
+	     * // Some state name examples
+	     *
+	     * // stateName can be a single top-level name (must be unique).
+	     * $stateProvider.state("home", {});
+	     *
+	     * // Or it can be a nested state name. This state is a child of the
+	     * // above "home" state.
+	     * $stateProvider.state("home.newest", {});
+	     *
+	     * // Nest states as deeply as needed.
+	     * $stateProvider.state("home.newest.abc.xyz.inception", {});
+	     *
+	     * // state() returns $stateProvider, so you can chain state declarations.
+	     * $stateProvider
+	     *   .state("home", {})
+	     *   .state("about", {})
+	     *   .state("contacts", {});
+	     * 
+ * + * @param {string} name A unique state name, e.g. "home", "about", "contacts". + * To create a parent/child state use a dot, e.g. "about.sales", "home.newest". + * @param {object} definition State configuration object. + */ + StateProvider.prototype.state = function (name, definition) { + if (predicates_1.isObject(name)) { + definition = name; + } + else { + definition.name = name; + } + this.stateRegistry.register(definition); + return this; + }; + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#onInvalid + * @methodOf ui.router.state.$stateProvider + * + * @description + * Registers a function to be injected and invoked when transitionTo has been called with an invalid + * state reference parameter + * + * This function can be injected with one some special values: + * - **`$to$`**: TargetState + * - **`$from$`**: TargetState + * + * @param {function} callback + * The function which will be injected and invoked, when a matching transition is started. + * The function may optionally return a {TargetState} or a Promise for a TargetState. If one + * is returned, it is treated as a redirect. + */ + StateProvider.prototype.onInvalid = function (callback) { + this.invalidCallbacks.push(callback); + }; + return StateProvider; + }()); + exports.StateProvider = StateProvider; + + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var hof_1 = __webpack_require__(5); + var module_1 = __webpack_require__(20); + var parseUrl = function (url) { + if (!predicates_1.isString(url)) + return false; + var root = url.charAt(0) === '^'; + return { val: root ? url.substring(1) : url, root: root }; + }; + /** + * @internalapi A internal global service + * + * StateBuilder is a factory for the internal [[State]] objects. + * + * When you register a state with the [[StateRegistry]], you register a plain old javascript object which + * conforms to the [[StateDeclaration]] interface. This factory takes that object and builds the corresponding + * [[State]] object, which has an API and is used internally. + * + * Custom properties or API may be added to the internal [[State]] object by registering a decorator function + * using the [[builder]] method. + */ + var StateBuilder = (function () { + function StateBuilder(matcher, $urlMatcherFactoryProvider) { + this.matcher = matcher; + var self = this; + var isRoot = function (state) { return state.name === ""; }; + var root = function () { return matcher.find(""); }; + this.builders = { + self: [function (state) { + state.self.$$state = function () { return state; }; + return state.self; + }], + parent: [function (state) { + if (isRoot(state)) + return null; + return matcher.find(self.parentName(state)) || root(); + }], + data: [function (state) { + if (state.parent && state.parent.data) { + state.data = state.self.data = common_1.inherit(state.parent.data, state.data); + } + return state.data; + }], + // Build a URLMatcher if necessary, either via a relative or absolute URL + url: [function (state) { + var stateDec = state; + var parsed = parseUrl(stateDec.url), parent = state.parent; + var url = !parsed ? stateDec.url : $urlMatcherFactoryProvider.compile(parsed.val, { + params: state.params || {}, + paramMap: function (paramConfig, isSearch) { + if (stateDec.reloadOnSearch === false && isSearch) + paramConfig = common_1.extend(paramConfig || {}, { dynamic: true }); + return paramConfig; + } + }); + if (!url) + return null; + if (!$urlMatcherFactoryProvider.isMatcher(url)) + throw new Error("Invalid url '" + url + "' in state '" + state + "'"); + return (parsed && parsed.root) ? url : ((parent && parent.navigable) || root()).url.append(url); + }], + // Keep track of the closest ancestor state that has a URL (i.e. is navigable) + navigable: [function (state) { + return !isRoot(state) && state.url ? state : (state.parent ? state.parent.navigable : null); + }], + params: [function (state) { + var makeConfigParam = function (config, id) { return module_1.Param.fromConfig(id, null, config); }; + var urlParams = (state.url && state.url.parameters({ inherit: false })) || []; + var nonUrlParams = common_1.values(common_1.map(common_1.omit(state.params || {}, urlParams.map(hof_1.prop('id'))), makeConfigParam)); + return urlParams.concat(nonUrlParams).map(function (p) { return [p.id, p]; }).reduce(common_1.applyPairs, {}); + }], + // Each framework-specific ui-router implementation should define its own `views` builder + // e.g., src/ng1/viewsBuilder.ts + views: [], + // Keep a full path from the root down to this state as this is needed for state activation. + path: [function (state) { + return state.parent ? state.parent.path.concat(state) : [state]; + }], + // Speed up $state.includes() as it's used a lot + includes: [function (state) { + var includes = state.parent ? common_1.extend({}, state.parent.includes) : {}; + includes[state.name] = true; + return includes; + }] + }; + } + /** + * Registers a [[BuilderFunction]] for a specific [[State]] property (e.g., `parent`, `url`, or `path`). + * More than one BuilderFunction can be registered for a given property. + * + * The BuilderFunction(s) will be used to define the property on any subsequently built [[State]] objects. + * + * @param name The name of the State property being registered for. + * @param fn The BuilderFunction which will be used to build the State property + * @returns a function which deregisters the BuilderFunction + */ + StateBuilder.prototype.builder = function (name, fn) { + var builders = this.builders; + var array = builders[name] || []; + // Backwards compat: if only one builder exists, return it, else return whole arary. + if (predicates_1.isString(name) && !predicates_1.isDefined(fn)) + return array.length > 1 ? array : array[0]; + if (!predicates_1.isString(name) || !predicates_1.isFunction(fn)) + return; + builders[name] = array; + builders[name].push(fn); + return function () { return builders[name].splice(builders[name].indexOf(fn, 1)) && null; }; + }; + /** + * Builds all of the properties on an essentially blank State object, returning a State object which has all its + * properties and API built. + * + * @param state an uninitialized State object + * @returns the built State object + */ + StateBuilder.prototype.build = function (state) { + var _a = this, matcher = _a.matcher, builders = _a.builders; + var parent = this.parentName(state); + if (parent && !matcher.find(parent)) + return null; + for (var key in builders) { + if (!builders.hasOwnProperty(key)) + continue; + var chain = builders[key].reduce(function (parentFn, step) { return function (_state) { return step(_state, parentFn); }; }, common_1.noop); + state[key] = chain(state); + } + return state; + }; + StateBuilder.prototype.parentName = function (state) { + var name = state.name || ""; + if (name.indexOf('.') !== -1) + return name.substring(0, name.lastIndexOf('.')); + if (!state.parent) + return ""; + return predicates_1.isString(state.parent) ? state.parent : state.parent.name; + }; + StateBuilder.prototype.name = function (state) { + var name = state.name; + if (name.indexOf('.') !== -1 || !state.parent) + return name; + var parentName = predicates_1.isString(state.parent) ? state.parent : state.parent.name; + return parentName ? parentName + "." + name : name; + }; + return StateBuilder; + }()); + exports.StateBuilder = StateBuilder; + + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** + * This module contains code for State Parameters. + * + * See [[ParamDeclaration]] + * @module params + * @preferred doc + */ + /** for typedoc */ + __export(__webpack_require__(21)); + __export(__webpack_require__(24)); + __export(__webpack_require__(25)); + __export(__webpack_require__(23)); + + +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module params */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var predicates_1 = __webpack_require__(4); + var coreservices_1 = __webpack_require__(6); + var urlMatcherConfig_1 = __webpack_require__(22); + var type_1 = __webpack_require__(23); + var paramTypes_1 = __webpack_require__(24); + var hasOwn = Object.prototype.hasOwnProperty; + var isShorthand = function (cfg) { return ["value", "type", "squash", "array", "dynamic"].filter(hasOwn.bind(cfg || {})).length === 0; }; + (function (DefType) { + DefType[DefType["PATH"] = 0] = "PATH"; + DefType[DefType["SEARCH"] = 1] = "SEARCH"; + DefType[DefType["CONFIG"] = 2] = "CONFIG"; + })(exports.DefType || (exports.DefType = {})); + var DefType = exports.DefType; + function unwrapShorthand(cfg) { + cfg = isShorthand(cfg) && { value: cfg } || cfg; + return common_1.extend(cfg, { + $$fn: predicates_1.isInjectable(cfg.value) ? cfg.value : function () { return cfg.value; } + }); + } + function getType(cfg, urlType, location, id) { + if (cfg.type && urlType && urlType.name !== 'string') + throw new Error("Param '" + id + "' has two type configurations."); + if (cfg.type && urlType && urlType.name === 'string' && paramTypes_1.paramTypes.type(cfg.type)) + return paramTypes_1.paramTypes.type(cfg.type); + if (urlType) + return urlType; + if (!cfg.type) + return (location === DefType.CONFIG ? paramTypes_1.paramTypes.type("any") : paramTypes_1.paramTypes.type("string")); + return cfg.type instanceof type_1.Type ? cfg.type : paramTypes_1.paramTypes.type(cfg.type); + } + /** + * returns false, true, or the squash value to indicate the "default parameter url squash policy". + */ + function getSquashPolicy(config, isOptional) { + var squash = config.squash; + if (!isOptional || squash === false) + return false; + if (!predicates_1.isDefined(squash) || squash == null) + return urlMatcherConfig_1.matcherConfig.defaultSquashPolicy(); + if (squash === true || predicates_1.isString(squash)) + return squash; + throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string"); + } + function getReplace(config, arrayMode, isOptional, squash) { + var replace, configuredKeys, defaultPolicy = [ + { from: "", to: (isOptional || arrayMode ? undefined : "") }, + { from: null, to: (isOptional || arrayMode ? undefined : "") } + ]; + replace = predicates_1.isArray(config.replace) ? config.replace : []; + if (predicates_1.isString(squash)) + replace.push({ from: squash, to: undefined }); + configuredKeys = common_1.map(replace, hof_1.prop("from")); + return common_1.filter(defaultPolicy, function (item) { return configuredKeys.indexOf(item.from) === -1; }).concat(replace); + } + var Param = (function () { + function Param(id, type, config, location) { + config = unwrapShorthand(config); + type = getType(config, type, location, id); + var arrayMode = getArrayMode(); + type = arrayMode ? type.$asArray(arrayMode, location === DefType.SEARCH) : type; + var isOptional = config.value !== undefined; + var dynamic = config.dynamic === true; + var squash = getSquashPolicy(config, isOptional); + var replace = getReplace(config, arrayMode, isOptional, squash); + // array config: param name (param[]) overrides default settings. explicit config overrides param name. + function getArrayMode() { + var arrayDefaults = { array: (location === DefType.SEARCH ? "auto" : false) }; + var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {}; + return common_1.extend(arrayDefaults, arrayParamNomenclature, config).array; + } + common_1.extend(this, { id: id, type: type, location: location, squash: squash, replace: replace, isOptional: isOptional, dynamic: dynamic, config: config, array: arrayMode }); + } + Param.prototype.isDefaultValue = function (value) { + return this.isOptional && this.type.equals(this.value(), value); + }; + /** + * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the + * default value, which may be the result of an injectable function. + */ + Param.prototype.value = function (value) { + var _this = this; + /** + * [Internal] Get the default value of a parameter, which may be an injectable function. + */ + var $$getDefaultValue = function () { + if (!coreservices_1.services.$injector) + throw new Error("Injectable functions cannot be called at configuration time"); + var defaultValue = coreservices_1.services.$injector.invoke(_this.config.$$fn); + if (defaultValue !== null && defaultValue !== undefined && !_this.type.is(defaultValue)) + throw new Error("Default value (" + defaultValue + ") for parameter '" + _this.id + "' is not an instance of Type (" + _this.type.name + ")"); + return defaultValue; + }; + var $replace = function (val) { + var replacement = common_1.map(common_1.filter(_this.replace, hof_1.propEq('from', val)), hof_1.prop("to")); + return replacement.length ? replacement[0] : val; + }; + value = $replace(value); + return !predicates_1.isDefined(value) ? $$getDefaultValue() : this.type.$normalize(value); + }; + Param.prototype.isSearch = function () { + return this.location === DefType.SEARCH; + }; + Param.prototype.validates = function (value) { + // There was no parameter value, but the param is optional + if ((!predicates_1.isDefined(value) || value === null) && this.isOptional) + return true; + // The value was not of the correct Type, and could not be decoded to the correct Type + var normalized = this.type.$normalize(value); + if (!this.type.is(normalized)) + return false; + // The value was of the correct type, but when encoded, did not match the Type's regexp + var encoded = this.type.encode(normalized); + return !(predicates_1.isString(encoded) && !this.type.pattern.exec(encoded)); + }; + Param.prototype.toString = function () { + return "{Param:" + this.id + " " + this.type + " squash: '" + this.squash + "' optional: " + this.isOptional + "}"; + }; + /** Creates a new [[Param]] from a CONFIG block */ + Param.fromConfig = function (id, type, config) { + return new Param(id, type, config, DefType.CONFIG); + }; + /** Creates a new [[Param]] from a url PATH */ + Param.fromPath = function (id, type, config) { + return new Param(id, type, config, DefType.PATH); + }; + /** Creates a new [[Param]] from a url SEARCH */ + Param.fromSearch = function (id, type, config) { + return new Param(id, type, config, DefType.SEARCH); + }; + Param.values = function (params, values) { + if (values === void 0) { values = {}; } + return params.map(function (param) { return [param.id, param.value(values[param.id])]; }).reduce(common_1.applyPairs, {}); + }; + /** + * Finds [[Param]] objects which have different param values + * + * Filters a list of [[Param]] objects to only those whose parameter values differ in two param value objects + * + * @param params: The list of Param objects to filter + * @param values1: The first set of parameter values + * @param values2: the second set of parameter values + * + * @returns any Param objects whose values were different between values1 and values2 + */ + Param.changed = function (params, values1, values2) { + if (values1 === void 0) { values1 = {}; } + if (values2 === void 0) { values2 = {}; } + return params.filter(function (param) { return !param.type.equals(values1[param.id], values2[param.id]); }); + }; + /** + * Checks if two param value objects are equal (for a set of [[Param]] objects) + * + * @param params The list of [[Param]] objects to check + * @param values1 The first set of param values + * @param values2 The second set of param values + * + * @returns true if the param values in values1 and values2 are equal + */ + Param.equals = function (params, values1, values2) { + if (values1 === void 0) { values1 = {}; } + if (values2 === void 0) { values2 = {}; } + return Param.changed(params, values1, values2).length === 0; + }; + /** Returns true if a the parameter values are valid, according to the Param definitions */ + Param.validates = function (params, values) { + if (values === void 0) { values = {}; } + return params.map(function (param) { return param.validates(values[param.id]); }).reduce(common_1.allTrueR, true); + }; + return Param; + }()); + exports.Param = Param; + + +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module url */ /** for typedoc */ + var predicates_1 = __webpack_require__(4); + var MatcherConfig = (function () { + function MatcherConfig() { + this._isCaseInsensitive = false; + this._isStrictMode = true; + this._defaultSquashPolicy = false; + } + MatcherConfig.prototype.caseInsensitive = function (value) { + return this._isCaseInsensitive = predicates_1.isDefined(value) ? value : this._isCaseInsensitive; + }; + MatcherConfig.prototype.strictMode = function (value) { + return this._isStrictMode = predicates_1.isDefined(value) ? value : this._isStrictMode; + }; + MatcherConfig.prototype.defaultSquashPolicy = function (value) { + if (predicates_1.isDefined(value) && value !== true && value !== false && !predicates_1.isString(value)) + throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string"); + return this._defaultSquashPolicy = predicates_1.isDefined(value) ? value : this._defaultSquashPolicy; + }; + return MatcherConfig; + }()); + exports.MatcherConfig = MatcherConfig; + // TODO: Do not export global instance; create one in UIRouter() constructor + exports.matcherConfig = new MatcherConfig(); + + +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module params */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + /** + * Wraps up a `Type` object to handle array values. + */ + function ArrayType(type, mode) { + var _this = this; + // Wrap non-array value as array + function arrayWrap(val) { return predicates_1.isArray(val) ? val : (predicates_1.isDefined(val) ? [val] : []); } + // Unwrap array value for "auto" mode. Return undefined for empty array. + function arrayUnwrap(val) { + switch (val.length) { + case 0: return undefined; + case 1: return mode === "auto" ? val[0] : val; + default: return val; + } + } + // Wraps type (.is/.encode/.decode) functions to operate on each value of an array + function arrayHandler(callback, allTruthyMode) { + return function handleArray(val) { + if (predicates_1.isArray(val) && val.length === 0) + return val; + var arr = arrayWrap(val); + var result = common_1.map(arr, callback); + return (allTruthyMode === true) ? common_1.filter(result, function (x) { return !x; }).length === 0 : arrayUnwrap(result); + }; + } + // Wraps type (.equals) functions to operate on each value of an array + function arrayEqualsHandler(callback) { + return function handleArray(val1, val2) { + var left = arrayWrap(val1), right = arrayWrap(val2); + if (left.length !== right.length) + return false; + for (var i = 0; i < left.length; i++) { + if (!callback(left[i], right[i])) + return false; + } + return true; + }; + } + ['encode', 'decode', 'equals', '$normalize'].map(function (name) { + _this[name] = (name === 'equals' ? arrayEqualsHandler : arrayHandler)(type[name].bind(type)); + }); + common_1.extend(this, { + name: type.name, + pattern: type.pattern, + is: arrayHandler(type.is.bind(type), true), + $arrayMode: mode + }); + } + /** + * Implements an interface to define custom parameter types that can be decoded from and encoded to + * string parameters matched in a URL. Used by [[UrlMatcher]] + * objects when matching or formatting URLs, or comparing or validating parameter values. + * + * See [[UrlMatcherFactory.type]] for more information on registering custom types. + * + * @example + * ``` + * + * { + * decode: function(val) { return parseInt(val, 10); }, + * encode: function(val) { return val && val.toString(); }, + * equals: function(a, b) { return this.is(a) && a === b; }, + * is: function(val) { return angular.isNumber(val) && isFinite(val) && val % 1 === 0; }, + * pattern: /\d+/ + * } + * ``` + */ + var Type = (function () { + /** + * @param def A configuration object which contains the custom type definition. The object's + * properties will override the default methods and/or pattern in `Type`'s public interface. + * @returns a new Type object + */ + function Type(def) { + this.pattern = /.*/; + common_1.extend(this, def); + } + // consider these four methods to be "abstract methods" that should be overridden + /** @inheritdoc */ + Type.prototype.is = function (val, key) { return true; }; + /** @inheritdoc */ + Type.prototype.encode = function (val, key) { return val; }; + /** @inheritdoc */ + Type.prototype.decode = function (val, key) { return val; }; + /** @inheritdoc */ + Type.prototype.equals = function (a, b) { return a == b; }; + Type.prototype.$subPattern = function () { + var sub = this.pattern.toString(); + return sub.substr(1, sub.length - 2); + }; + Type.prototype.toString = function () { + return "{Type:" + this.name + "}"; + }; + /** Given an encoded string, or a decoded object, returns a decoded object */ + Type.prototype.$normalize = function (val) { + return this.is(val) ? val : this.decode(val); + }; + /** + * Wraps an existing custom Type as an array of Type, depending on 'mode'. + * e.g.: + * - urlmatcher pattern "/path?{queryParam[]:int}" + * - url: "/path?queryParam=1&queryParam=2 + * - $stateParams.queryParam will be [1, 2] + * if `mode` is "auto", then + * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1 + * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2] + */ + Type.prototype.$asArray = function (mode, isSearch) { + if (!mode) + return this; + if (mode === "auto" && !isSearch) + throw new Error("'auto' array mode is for query parameters only"); + return new ArrayType(this, mode); + }; + return Type; + }()); + exports.Type = Type; + + +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module params */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var hof_1 = __webpack_require__(5); + var coreservices_1 = __webpack_require__(6); + var type_1 = __webpack_require__(23); + // Use tildes to pre-encode slashes. + // If the slashes are simply URLEncoded, the browser can choose to pre-decode them, + // and bidirectional encoding/decoding fails. + // Tilde was chosen because it's not a RFC 3986 section 2.2 Reserved Character + function valToString(val) { return val != null ? val.toString().replace(/~/g, "~~").replace(/\//g, "~2F") : val; } + function valFromString(val) { return val != null ? val.toString().replace(/~2F/g, "/").replace(/~~/g, "~") : val; } + var ParamTypes = (function () { + function ParamTypes() { + this.enqueue = true; + this.typeQueue = []; + this.defaultTypes = { + "hash": { + encode: valToString, + decode: valFromString, + is: hof_1.is(String), + pattern: /.*/, + equals: hof_1.val(true) + }, + "string": { + encode: valToString, + decode: valFromString, + is: hof_1.is(String), + pattern: /[^/]*/ + }, + "int": { + encode: valToString, + decode: function (val) { return parseInt(val, 10); }, + is: function (val) { return predicates_1.isDefined(val) && this.decode(val.toString()) === val; }, + pattern: /-?\d+/ + }, + "bool": { + encode: function (val) { return val && 1 || 0; }, + decode: function (val) { return parseInt(val, 10) !== 0; }, + is: hof_1.is(Boolean), + pattern: /0|1/ + }, + "date": { + encode: function (val) { + return !this.is(val) ? undefined : [ + val.getFullYear(), + ('0' + (val.getMonth() + 1)).slice(-2), + ('0' + val.getDate()).slice(-2) + ].join("-"); + }, + decode: function (val) { + if (this.is(val)) + return val; + var match = this.capture.exec(val); + return match ? new Date(match[1], match[2] - 1, match[3]) : undefined; + }, + is: function (val) { return val instanceof Date && !isNaN(val.valueOf()); }, + equals: function (l, r) { + return ['getFullYear', 'getMonth', 'getDate'] + .reduce(function (acc, fn) { return acc && l[fn]() === r[fn](); }, true); + }, + pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/, + capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/ + }, + "json": { + encode: common_1.toJson, + decode: common_1.fromJson, + is: hof_1.is(Object), + equals: common_1.equals, + pattern: /[^/]*/ + }, + "any": { + encode: common_1.identity, + decode: common_1.identity, + equals: common_1.equals, + pattern: /.*/ + } + }; + // Register default types. Store them in the prototype of this.types. + var makeType = function (definition, name) { return new type_1.Type(common_1.extend({ name: name }, definition)); }; + this.types = common_1.inherit(common_1.map(this.defaultTypes, makeType), {}); + } + ParamTypes.prototype.type = function (name, definition, definitionFn) { + if (!predicates_1.isDefined(definition)) + return this.types[name]; + if (this.types.hasOwnProperty(name)) + throw new Error("A type named '" + name + "' has already been defined."); + this.types[name] = new type_1.Type(common_1.extend({ name: name }, definition)); + if (definitionFn) { + this.typeQueue.push({ name: name, def: definitionFn }); + if (!this.enqueue) + this._flushTypeQueue(); + } + return this; + }; + ParamTypes.prototype._flushTypeQueue = function () { + while (this.typeQueue.length) { + var type = this.typeQueue.shift(); + if (type.pattern) + throw new Error("You cannot override a type's .pattern at runtime."); + common_1.extend(this.types[type.name], coreservices_1.services.$injector.invoke(type.def)); + } + }; + return ParamTypes; + }()); + exports.ParamTypes = ParamTypes; + exports.paramTypes = new ParamTypes(); + + +/***/ }, +/* 25 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module params */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var StateParams = (function () { + function StateParams(params) { + if (params === void 0) { params = {}; } + common_1.extend(this, params); + } + /** + * Merges a set of parameters with all parameters inherited between the common parents of the + * current state and a given destination state. + * + * @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. + */ + StateParams.prototype.$inherit = function (newParams, $current, $to) { + var parents = common_1.ancestors($current, $to), parentParams, inherited = {}, inheritList = []; + for (var i in parents) { + if (!parents[i] || !parents[i].params) + continue; + parentParams = Object.keys(parents[i].params); + if (!parentParams.length) + continue; + for (var j in parentParams) { + if (inheritList.indexOf(parentParams[j]) >= 0) + continue; + inheritList.push(parentParams[j]); + inherited[parentParams[j]] = this[parentParams[j]]; + } + } + return common_1.extend({}, inherited, newParams); + }; + ; + return StateParams; + }()); + exports.StateParams = StateParams; + + +/***/ }, +/* 26 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** for typedoc */ + var hof_1 = __webpack_require__(5); + var param_1 = __webpack_require__(21); + var rejectFactory_1 = __webpack_require__(10); + var targetState_1 = __webpack_require__(27); + var viewHooks_1 = __webpack_require__(28); + var enterExitHooks_1 = __webpack_require__(29); + var resolveHooks_1 = __webpack_require__(30); + var coreservices_1 = __webpack_require__(6); + /** + * This class: + * + * * Takes a blank transition object and adds all the hooks necessary for it to behave like a state transition. + * + * * Runs the transition, returning a chained promise which: + * * transforms the resolved Transition.promise to the final destination state. + * * manages the rejected Transition.promise, checking for Dynamic or Redirected transitions + * + * * Registers a handler to update global $state data such as "active transitions" and "current state/params" + * + * * Registers view hooks, which maintain the list of active view configs and sync with/update the ui-views + * + * * Registers onEnter/onRetain/onExit hooks which delegate to the state's hooks of the same name, at the appropriate time + * + * * Registers eager and lazy resolve hooks + */ + var TransitionManager = (function () { + function TransitionManager(transition, $transitions, $urlRouter, $view, // service + $state, globals) { + this.transition = transition; + this.$transitions = $transitions; + this.$urlRouter = $urlRouter; + this.$view = $view; + this.$state = $state; + this.globals = globals; + this.$q = coreservices_1.services.$q; + this.viewHooks = new viewHooks_1.ViewHooks(transition, $view); + this.enterExitHooks = new enterExitHooks_1.EnterExitHooks(transition); + this.resolveHooks = new resolveHooks_1.ResolveHooks(transition); + this.treeChanges = transition.treeChanges(); + this.registerUpdateGlobalState(); + this.viewHooks.registerHooks(); + this.enterExitHooks.registerHooks(); + this.resolveHooks.registerHooks(); + } + TransitionManager.prototype.runTransition = function () { + var _this = this; + this.globals.transitionHistory.enqueue(this.transition); + return this.transition.run() + .then(function (trans) { return trans.to(); }) // resolve to the final state (TODO: good? bad?) + .catch(function (error) { return _this.transRejected(error); }); // if rejected, handle dynamic and redirect + }; + TransitionManager.prototype.registerUpdateGlobalState = function () { + // After globals.current is updated at priority: 10000 + this.transition.onSuccess({}, this.updateUrl.bind(this), { priority: 9999 }); + }; + TransitionManager.prototype.transRejected = function (error) { + var _a = this, transition = _a.transition, $state = _a.$state, $q = _a.$q; + // Handle redirect and abort + if (error instanceof rejectFactory_1.TransitionRejection) { + if (error.type === rejectFactory_1.RejectType.IGNORED) { + // Update $stateParmas/$state.params/$location.url if transition ignored, but dynamic params have changed. + var dynamic = $state.$current.parameters().filter(hof_1.prop('dynamic')); + if (!param_1.Param.equals(dynamic, $state.params, transition.params())) { + this.updateUrl(); + } + return $state.current; + } + if (error.type === rejectFactory_1.RejectType.SUPERSEDED && error.redirected && error.detail instanceof targetState_1.TargetState) { + return this._redirectMgr(transition.redirect(error.detail)).runTransition(); + } + if (error.type === rejectFactory_1.RejectType.ABORTED) { + this.$urlRouter.update(); + } + } + this.$transitions.defaultErrorHandler()(error); + return $q.reject(error); + }; + TransitionManager.prototype.updateUrl = function () { + var transition = this.transition; + var _a = this, $urlRouter = _a.$urlRouter, $state = _a.$state; + var options = transition.options(); + var toState = transition.$to(); + if (options.location && $state.$current.navigable) { + $urlRouter.push($state.$current.navigable.url, $state.params, { replace: options.location === 'replace' }); + } + $urlRouter.update(true); + }; + TransitionManager.prototype._redirectMgr = function (redirect) { + var _a = this, $transitions = _a.$transitions, $urlRouter = _a.$urlRouter, $view = _a.$view, $state = _a.$state, globals = _a.globals; + return new TransitionManager(redirect, $transitions, $urlRouter, $view, $state, globals); + }; + return TransitionManager; + }()); + exports.TransitionManager = TransitionManager; + + +/***/ }, +/* 27 */ +/***/ function(module, exports) { + + /** @module state */ /** for typedoc */ + "use strict"; + /** + * @ngdoc object + * @name ui.router.state.type:TargetState + * + * @description + * Encapsulate the desired target of a transition. + * Wraps an identifier for a state, a set of parameters, and transition options with the definition of the state. + * + * @param {StateOrName} _identifier An identifier for a state. Either a fully-qualified path, or the object + * used to define the state. + * @param {IState} _definition The `State` object definition. + * @param {ParamsOrArray} _params Parameters for the target state + * @param {TransitionOptions} _options Transition options. + */ + var TargetState = (function () { + function TargetState(_identifier, _definition, _params, _options) { + if (_params === void 0) { _params = {}; } + if (_options === void 0) { _options = {}; } + this._identifier = _identifier; + this._definition = _definition; + this._options = _options; + this._params = _params || {}; + } + TargetState.prototype.name = function () { + return this._definition && this._definition.name || this._identifier; + }; + TargetState.prototype.identifier = function () { + return this._identifier; + }; + TargetState.prototype.params = function () { + return this._params; + }; + TargetState.prototype.$state = function () { + return this._definition; + }; + TargetState.prototype.state = function () { + return this._definition && this._definition.self; + }; + TargetState.prototype.options = function () { + return this._options; + }; + TargetState.prototype.exists = function () { + return !!(this._definition && this._definition.self); + }; + TargetState.prototype.valid = function () { + return !this.error(); + }; + TargetState.prototype.error = function () { + var base = this.options().relative; + if (!this._definition && !!base) { + var stateName = base.name ? base.name : base; + return "Could not resolve '" + this.name() + "' from state '" + stateName + "'"; + } + if (!this._definition) + return "No such state '" + this.name() + "'"; + if (!this._definition.self) + return "State '" + this.name() + "' has an invalid definition"; + }; + return TargetState; + }()); + exports.TargetState = TargetState; + + +/***/ }, +/* 28 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var coreservices_1 = __webpack_require__(6); + var ViewHooks = (function () { + function ViewHooks(transition, $view) { + this.transition = transition; + this.$view = $view; + this.treeChanges = transition.treeChanges(); + this.enteringViews = transition.views("entering"); + this.exitingViews = transition.views("exiting"); + } + ViewHooks.prototype.loadAllEnteringViews = function () { + return coreservices_1.services.$q.all(this.enteringViews.map(function (view) { return view.load(); })).then(common_1.noop); + }; + ViewHooks.prototype.updateViews = function () { + var $view = this.$view; + this.exitingViews.forEach(function (viewConfig) { return $view.deactivateViewConfig(viewConfig); }); + this.enteringViews.forEach(function (viewConfig) { return $view.activateViewConfig(viewConfig); }); + $view.sync(); + }; + ViewHooks.prototype.registerHooks = function () { + if (this.enteringViews.length) { + this.transition.onStart({}, this.loadAllEnteringViews.bind(this)); + } + if (this.exitingViews.length || this.enteringViews.length) + this.transition.onSuccess({}, this.updateViews.bind(this)); + }; + return ViewHooks; + }()); + exports.ViewHooks = ViewHooks; + + +/***/ }, +/* 29 */ +/***/ function(module, exports) { + + "use strict"; + var EnterExitHooks = (function () { + function EnterExitHooks(transition) { + this.transition = transition; + } + EnterExitHooks.prototype.registerHooks = function () { + this.registerOnEnterHooks(); + this.registerOnRetainHooks(); + this.registerOnExitHooks(); + }; + EnterExitHooks.prototype.registerOnEnterHooks = function () { + var _this = this; + this.transition.entering().filter(function (state) { return !!state.onEnter; }) + .forEach(function (state) { return _this.transition.onEnter({ entering: state.name }, state.onEnter); }); + }; + EnterExitHooks.prototype.registerOnRetainHooks = function () { + var _this = this; + this.transition.retained().filter(function (state) { return !!state.onRetain; }) + .forEach(function (state) { return _this.transition.onRetain({ retained: state.name }, state.onRetain); }); + }; + EnterExitHooks.prototype.registerOnExitHooks = function () { + var _this = this; + this.transition.exiting().filter(function (state) { return !!state.onExit; }) + .forEach(function (state) { return _this.transition.onExit({ exiting: state.name }, state.onExit); }); + }; + return EnterExitHooks; + }()); + exports.EnterExitHooks = EnterExitHooks; + + +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var interface_1 = __webpack_require__(31); + var hof_2 = __webpack_require__(5); + var resolvable_1 = __webpack_require__(32); + var LAZY = interface_1.ResolvePolicy[interface_1.ResolvePolicy.LAZY]; + var EAGER = interface_1.ResolvePolicy[interface_1.ResolvePolicy.EAGER]; + /** + * Registers Eager and Lazy (for entering states) resolve hooks + * + * * registers a hook that resolves EAGER resolves, for the To Path, onStart of the transition + * * registers a hook that resolves LAZY resolves, for each state, before it is entered + */ + var ResolveHooks = (function () { + function ResolveHooks(transition) { + this.transition = transition; + } + ResolveHooks.prototype.registerHooks = function () { + var treeChanges = this.transition.treeChanges(); + /** a function which resolves any EAGER Resolvables for a Path */ + $eagerResolvePath.$inject = ['$transition$']; + function $eagerResolvePath($transition$) { + return common_1.tail(treeChanges.to).resolveContext.resolvePath(common_1.extend({ transition: $transition$ }, { resolvePolicy: EAGER })); + } + /** Returns a function which pre-resolves any LAZY Resolvables for a Node in a Path */ + $lazyResolveEnteringState.$inject = ['$state$', '$transition$']; + function $lazyResolveEnteringState($state$, $transition$) { + var node = common_1.find(treeChanges.entering, hof_1.propEq('state', $state$)); + // A new Resolvable contains all the resolved data in this context as a single object, for injection as `$resolve$` + var context = node.resolveContext; + var $resolve$ = new resolvable_1.Resolvable("$resolve$", function () { return common_1.map(context.getResolvables(), function (r) { return r.data; }); }); + var options = common_1.extend({ transition: $transition$ }, { resolvePolicy: LAZY }); + // Resolve all the LAZY resolves, then resolve the `$resolve$` object, then add `$resolve$` to the context + return context.resolvePathElement(node.state, options) + .then(function () { return $resolve$.resolveResolvable(context); }) + .then(function () { return context.addResolvables({ $resolve$: $resolve$ }, node.state); }); + } + // Resolve eager resolvables before when the transition starts + this.transition.onStart({}, $eagerResolvePath, { priority: 1000 }); + // Resolve lazy resolvables before each state is entered + this.transition.onEnter({ entering: hof_2.val(true) }, $lazyResolveEnteringState, { priority: 1000 }); + }; + return ResolveHooks; + }()); + exports.ResolveHooks = ResolveHooks; + + +/***/ }, +/* 31 */ +/***/ function(module, exports) { + + "use strict"; + // Defines the available policies and their ordinals. + (function (ResolvePolicy) { + ResolvePolicy[ResolvePolicy["JIT"] = 0] = "JIT"; + ResolvePolicy[ResolvePolicy["LAZY"] = 1] = "LAZY"; + ResolvePolicy[ResolvePolicy["EAGER"] = 2] = "EAGER"; // Eager resolves are resolved before the transition starts. + })(exports.ResolvePolicy || (exports.ResolvePolicy = {})); + var ResolvePolicy = exports.ResolvePolicy; + + +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module resolve */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var predicates_1 = __webpack_require__(4); + var coreservices_1 = __webpack_require__(6); + var trace_1 = __webpack_require__(12); + /** + * The basic building block for the resolve system. + * + * Resolvables encapsulate a state's resolve's resolveFn, the resolveFn's declared dependencies, the wrapped (.promise), + * and the unwrapped-when-complete (.data) result of the resolveFn. + * + * Resolvable.get() either retrieves the Resolvable's existing promise, or else invokes resolve() (which invokes the + * resolveFn) and returns the resulting promise. + * + * Resolvable.get() and Resolvable.resolve() both execute within a context path, which is passed as the first + * parameter to those fns. + */ + var Resolvable = (function () { + function Resolvable(name, resolveFn, preResolvedData) { + this.promise = undefined; + common_1.extend(this, { + name: name, + resolveFn: resolveFn, + deps: coreservices_1.services.$injector.annotate(resolveFn, coreservices_1.services.$injector.strictDi), + data: preResolvedData + }); + } + // synchronous part: + // - sets up the Resolvable's promise + // - retrieves dependencies' promises + // - returns promise for async part + // asynchronous part: + // - wait for dependencies promises to resolve + // - invoke the resolveFn + // - wait for resolveFn promise to resolve + // - store unwrapped data + // - resolve the Resolvable's promise + Resolvable.prototype.resolveResolvable = function (resolveContext, options) { + var _this = this; + if (options === void 0) { options = {}; } + var _a = this, name = _a.name, deps = _a.deps, resolveFn = _a.resolveFn; + trace_1.trace.traceResolveResolvable(this, options); + // First, set up an overall deferred/promise for this Resolvable + var deferred = coreservices_1.services.$q.defer(); + this.promise = deferred.promise; + // Load a map of all resolvables for this state from the context path + // Omit the current Resolvable from the result, so we don't try to inject this into this + var ancestorsByName = resolveContext.getResolvables(null, { omitOwnLocals: [name] }); + // Limit the ancestors Resolvables map to only those that the current Resolvable fn's annotations depends on + var depResolvables = common_1.pick(ancestorsByName, deps); + // Get promises (or synchronously invoke resolveFn) for deps + var depPromises = common_1.map(depResolvables, function (resolvable) { return resolvable.get(resolveContext, options); }); + // Return a promise chain that waits for all the deps to resolve, then invokes the resolveFn passing in the + // dependencies as locals, then unwraps the resulting promise's data. + return coreservices_1.services.$q.all(depPromises).then(function (locals) { + try { + var result = coreservices_1.services.$injector.invoke(resolveFn, null, locals); + deferred.resolve(result); + } + catch (error) { + deferred.reject(error); + } + return _this.promise; + }).then(function (data) { + _this.data = data; + trace_1.trace.traceResolvableResolved(_this, options); + return _this.promise; + }); + }; + Resolvable.prototype.get = function (resolveContext, options) { + return this.promise || this.resolveResolvable(resolveContext, options); + }; + Resolvable.prototype.toString = function () { + return "Resolvable(name: " + this.name + ", requires: [" + this.deps + "])"; + }; + /** + * Validates the result map as a "resolve:" style object, then transforms the resolves into Resolvables + */ + Resolvable.makeResolvables = function (resolves) { + // If a hook result is an object, it should be a map of strings to functions. + var invalid = common_1.filter(resolves, hof_1.not(predicates_1.isInjectable)), keys = Object.keys(invalid); + if (keys.length) + throw new Error("Invalid resolve key/value: " + keys[0] + "/" + invalid[keys[0]]); + return common_1.map(resolves, function (fn, name) { return new Resolvable(name, fn); }); + }; + return Resolvable; + }()); + exports.Resolvable = Resolvable; + + +/***/ }, +/* 33 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module state */ /** for typedoc */ + "use strict"; + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + /** + * @ngdoc object + * @name ui.router.state.type:State + * + * @description + * Definition object for states. Includes methods for manipulating the state heirarchy. + * + * @param {Object} config A configuration object hash that includes the results of user-supplied + * values, as well as values from `StateBuilder`. + * + * @returns {Object} Returns a new `State` object. + */ + var State = (function () { + function State(config) { + common_1.extend(this, config); + // Object.freeze(this); + } + /** + * @ngdoc function + * @name ui.router.state.type:State#is + * @methodOf ui.router.state.type:State + * + * @description + * Compares the identity of the state against the passed value, which is either an object + * reference to the actual `State` instance, the original definition object passed to + * `$stateProvider.state()`, or the fully-qualified name. + * + * @param {Object} ref Can be one of (a) a `State` instance, (b) an object that was passed + * into `$stateProvider.state()`, (c) the fully-qualified name of a state as a string. + * @returns {boolean} Returns `true` if `ref` matches the current `State` instance. + */ + State.prototype.is = function (ref) { + return this === ref || this.self === ref || this.fqn() === ref; + }; + /** + * @ngdoc function + * @name ui.router.state.type:State#fqn + * @methodOf ui.router.state.type:State + * + * @description + * Returns the fully-qualified name of the state, based on its current position in the tree. + * + * @returns {string} Returns a dot-separated name of the state. + */ + State.prototype.fqn = function () { + if (!this.parent || !(this.parent instanceof this.constructor)) + return this.name; + var name = this.parent.fqn(); + return name ? name + "." + this.name : this.name; + }; + /** + * @ngdoc function + * @name ui.router.state.type:State#root + * @methodOf ui.router.state.type:State + * + * @description + * Returns the root node of this state's tree. + * + * @returns {State} The root of this state's tree. + */ + State.prototype.root = function () { + return this.parent && this.parent.root() || this; + }; + State.prototype.parameters = function (opts) { + opts = common_1.defaults(opts, { inherit: true }); + var inherited = opts.inherit && this.parent && this.parent.parameters() || []; + return inherited.concat(common_1.values(this.params)); + }; + State.prototype.parameter = function (id, opts) { + if (opts === void 0) { opts = {}; } + return (this.url && this.url.parameter(id, opts) || + common_1.find(common_1.values(this.params), hof_1.propEq('id', id)) || + opts.inherit && this.parent && this.parent.parameter(id)); + }; + State.prototype.toString = function () { + return this.fqn(); + }; + return State; + }()); + exports.State = State; + + +/***/ }, +/* 34 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** for typedoc */ + var predicates_1 = __webpack_require__(4); + var StateMatcher = (function () { + function StateMatcher(_states) { + this._states = _states; + } + StateMatcher.prototype.isRelative = function (stateName) { + stateName = stateName || ""; + return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0; + }; + StateMatcher.prototype.find = function (stateOrName, base) { + if (!stateOrName && stateOrName !== "") + return undefined; + var isStr = predicates_1.isString(stateOrName); + var name = isStr ? stateOrName : stateOrName.name; + if (this.isRelative(name)) + name = this.resolvePath(name, base); + var state = this._states[name]; + if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) { + return state; + } + return undefined; + }; + StateMatcher.prototype.resolvePath = function (name, base) { + if (!base) + throw new Error("No reference point given for path '" + name + "'"); + var baseState = this.find(base); + var splitName = name.split("."), i = 0, pathLength = splitName.length, current = baseState; + for (; i < pathLength; i++) { + if (splitName[i] === "" && i === 0) { + current = baseState; + continue; + } + if (splitName[i] === "^") { + if (!current.parent) + throw new Error("Path '" + name + "' not valid for state '" + baseState.name + "'"); + current = current.parent; + continue; + } + break; + } + var relName = splitName.slice(i).join("."); + return current.name + (current.name && relName ? "." : "") + relName; + }; + return StateMatcher; + }()); + exports.StateMatcher = StateMatcher; + + +/***/ }, +/* 35 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var module_1 = __webpack_require__(17); + var StateQueueManager = (function () { + function StateQueueManager(states, builder, $urlRouterProvider) { + this.states = states; + this.builder = builder; + this.$urlRouterProvider = $urlRouterProvider; + this.queue = []; + } + StateQueueManager.prototype.register = function (config) { + var _a = this, states = _a.states, queue = _a.queue, $state = _a.$state; + // Wrap a new object around the state so we can store our private details easily. + // @TODO: state = new State(extend({}, config, { ... })) + var state = common_1.inherit(new module_1.State(), common_1.extend({}, config, { + self: config, + resolve: config.resolve || {}, + toString: function () { return config.name; } + })); + if (!predicates_1.isString(state.name)) + throw new Error("State must have a valid name"); + if (states.hasOwnProperty(state.name) || common_1.pluck(queue, 'name').indexOf(state.name) !== -1) + throw new Error("State '" + state.name + "' is already defined"); + queue.push(state); + if (this.$state) { + this.flush($state); + } + return state; + }; + StateQueueManager.prototype.flush = function ($state) { + var _a = this, queue = _a.queue, states = _a.states, builder = _a.builder; + var result, state, orphans = [], orphanIdx, previousQueueLength = {}; + while (queue.length > 0) { + state = queue.shift(); + result = builder.build(state); + orphanIdx = orphans.indexOf(state); + if (result) { + if (states.hasOwnProperty(state.name)) + throw new Error("State '" + name + "' is already defined"); + states[state.name] = state; + this.attachRoute($state, state); + if (orphanIdx >= 0) + orphans.splice(orphanIdx, 1); + continue; + } + var prev = previousQueueLength[state.name]; + previousQueueLength[state.name] = queue.length; + if (orphanIdx >= 0 && prev === queue.length) { + // Wait until two consecutive iterations where no additional states were dequeued successfully. + throw new Error("Cannot register orphaned state '" + state.name + "'"); + } + else if (orphanIdx < 0) { + orphans.push(state); + } + queue.push(state); + } + return states; + }; + StateQueueManager.prototype.autoFlush = function ($state) { + this.$state = $state; + this.flush($state); + }; + StateQueueManager.prototype.attachRoute = function ($state, state) { + var $urlRouterProvider = this.$urlRouterProvider; + if (state[common_1.abstractKey] || !state.url) + return; + $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) { + if ($state.$current.navigable !== state || !common_1.equalForKeys($match, $stateParams)) { + $state.transitionTo(state, $match, { inherit: true }); + } + }]); + }; + return StateQueueManager; + }()); + exports.StateQueueManager = StateQueueManager; + + +/***/ }, +/* 36 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module state */ /** for typedoc */ + "use strict"; + var stateMatcher_1 = __webpack_require__(34); + var stateBuilder_1 = __webpack_require__(19); + var stateQueueManager_1 = __webpack_require__(35); + var StateRegistry = (function () { + function StateRegistry(urlMatcherFactory, urlRouterProvider) { + this.states = {}; + this.matcher = new stateMatcher_1.StateMatcher(this.states); + this.builder = new stateBuilder_1.StateBuilder(this.matcher, urlMatcherFactory); + this.stateQueue = new stateQueueManager_1.StateQueueManager(this.states, this.builder, urlRouterProvider); + var rootStateDef = { + name: '', + url: '^', + views: null, + params: { + '#': { value: null, type: 'hash' } + }, + abstract: true + }; + var _root = this._root = this.stateQueue.register(rootStateDef); + _root.navigable = null; + } + StateRegistry.prototype.root = function () { + return this._root; + }; + StateRegistry.prototype.register = function (stateDefinition) { + return this.stateQueue.register(stateDefinition); + }; + StateRegistry.prototype.get = function (stateOrName, base) { + var _this = this; + if (arguments.length === 0) + return Object.keys(this.states).map(function (name) { return _this.states[name].self; }); + var found = this.matcher.find(stateOrName, base); + return found && found.self || null; + }; + StateRegistry.prototype.decorator = function (name, func) { + return this.builder.builder(name, func); + }; + return StateRegistry; + }()); + exports.StateRegistry = StateRegistry; + + +/***/ }, +/* 37 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module state */ /** */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var queue_1 = __webpack_require__(8); + var coreservices_1 = __webpack_require__(6); + var pathFactory_1 = __webpack_require__(38); + var node_1 = __webpack_require__(39); + var transitionService_1 = __webpack_require__(43); + var rejectFactory_1 = __webpack_require__(10); + var targetState_1 = __webpack_require__(27); + var transitionManager_1 = __webpack_require__(26); + var param_1 = __webpack_require__(21); + var glob_1 = __webpack_require__(7); + var common_2 = __webpack_require__(3); + var common_3 = __webpack_require__(3); + var StateService = (function () { + function StateService($view, $urlRouter, $transitions, stateRegistry, stateProvider, globals) { + this.$view = $view; + this.$urlRouter = $urlRouter; + this.$transitions = $transitions; + this.stateRegistry = stateRegistry; + this.stateProvider = stateProvider; + this.globals = globals; + this.rejectFactory = new rejectFactory_1.RejectFactory(); + var getters = ['current', '$current', 'params', 'transition']; + var boundFns = Object.keys(StateService.prototype).filter(function (key) { return getters.indexOf(key) === -1; }); + common_3.bindFunctions(StateService.prototype, this, this, boundFns); + } + Object.defineProperty(StateService.prototype, "transition", { + get: function () { return this.globals.transition; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(StateService.prototype, "params", { + get: function () { return this.globals.params; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(StateService.prototype, "current", { + get: function () { return this.globals.current; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(StateService.prototype, "$current", { + get: function () { return this.globals.$current; }, + enumerable: true, + configurable: true + }); + /** + * Invokes the onInvalid callbacks, in natural order. Each callback's return value is checked in sequence + * until one of them returns an instance of TargetState. The results of the callbacks are wrapped + * in $q.when(), so the callbacks may return promises. + * + * If a callback returns an TargetState, then it is used as arguments to $state.transitionTo() and + * the result returned. + */ + StateService.prototype._handleInvalidTargetState = function (fromPath, $to$) { + var _this = this; + var latestThing = function () { return _this.globals.transitionHistory.peekTail(); }; + var latest = latestThing(); + var $from$ = pathFactory_1.PathFactory.makeTargetState(fromPath); + var callbackQueue = new queue_1.Queue([].concat(this.stateProvider.invalidCallbacks)); + var rejectFactory = this.rejectFactory; + var $q = coreservices_1.services.$q, $injector = coreservices_1.services.$injector; + var invokeCallback = function (callback) { return $q.when($injector.invoke(callback, null, { $to$: $to$, $from$: $from$ })); }; + var checkForRedirect = function (result) { + if (!(result instanceof targetState_1.TargetState)) { + return; + } + var target = result; + // Recreate the TargetState, in case the state is now defined. + target = _this.target(target.identifier(), target.params(), target.options()); + if (!target.valid()) + return rejectFactory.invalid(target.error()); + if (latestThing() !== latest) + return rejectFactory.superseded(); + return _this.transitionTo(target.identifier(), target.params(), target.options()); + }; + function invokeNextCallback() { + var nextCallback = callbackQueue.dequeue(); + if (nextCallback === undefined) + return rejectFactory.invalid($to$.error()); + return invokeCallback(nextCallback).then(checkForRedirect).then(function (result) { return result || invokeNextCallback(); }); + } + return invokeNextCallback(); + }; + /** + * @ngdoc function + * @name ui.router.state.$state#reload + * @methodOf ui.router.state.$state + * + * @description + * A method that force reloads the current state, or a partial state hierarchy. All resolves are re-resolved, + * controllers reinstantiated, and events re-fired. + * + * @example + *
+	     * let app angular.module('app', ['ui.router']);
+	     *
+	     * app.controller('ctrl', function ($scope, $state) {
+	     *   $scope.reload = function(){
+	     *     $state.reload();
+	     *   }
+	     * });
+	     * 
+ * + * `reload()` is just an alias for: + *
+	     * $state.transitionTo($state.current, $stateParams, {
+	     *   reload: true, inherit: false, notify: true
+	     * });
+	     * 
+ * + * @param {string=|object=} reloadState - A state name or a state object, which is the root of the resolves to be re-resolved. + * @example + *
+	     * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item'
+	     * //and current state is 'contacts.detail.item'
+	     * let app angular.module('app', ['ui.router']);
+	     *
+	     * app.controller('ctrl', function ($scope, $state) {
+	     *   $scope.reload = function(){
+	     *     //will reload 'contact.detail' and nested 'contact.detail.item' states
+	     *     $state.reload('contact.detail');
+	     *   }
+	     * });
+	     * 
+ * + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + StateService.prototype.reload = function (reloadState) { + return this.transitionTo(this.current, this.params, { + reload: predicates_1.isDefined(reloadState) ? reloadState : true, + inherit: false, + notify: false + }); + }; + ; + /** + * @ngdoc function + * @name ui.router.state.$state#go + * @methodOf ui.router.state.$state + * + * @description + * Convenience method for transitioning to a new state. `$state.go` calls + * `$state.transitionTo` internally but automatically sets options to + * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. + * This allows you to easily use an absolute or relative to path and specify + * only the parameters you'd like to update (while letting unspecified parameters + * inherit from the currently active ancestor states). + * + * @example + *
+	     * let app = angular.module('app', ['ui.router']);
+	     *
+	     * app.controller('ctrl', function ($scope, $state) {
+	     *   $scope.changeState = function () {
+	     *     $state.go('contact.detail');
+	     *   };
+	     * });
+	     * 
+ * + * + * @param {string} to Absolute state name or relative state path. Some examples: + * + * - `$state.go('contact.detail')` - will go to the `contact.detail` state + * - `$state.go('^')` - will go to a parent state + * - `$state.go('^.sibling')` - will go to a sibling state + * - `$state.go('.child.grandchild')` - will go to grandchild state + * + * @param {object=} params A map of the parameters that will be sent to the state, + * will populate $stateParams. Any parameters that are not specified will be inherited from currently + * defined parameters. This allows, for example, going to a sibling state that shares parameters + * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e. + * transitioning to a sibling will get you the parameters for all parents, transitioning to a child + * will get you all current parameters, etc. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params + * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd + * use this when you want to force a reload when *everything* is the same, including search params. + * + * @returns {promise} A promise representing the state of the new transition. + * + * Possible success values: + * + * - $state.current + * + *
Possible rejection values: + * + * - 'transition superseded' - when a newer transition has been started after this one + * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener + * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or + * when a `$stateNotFound` `event.retry` promise errors. + * - 'transition failed' - when a state has been unsuccessfully found after 2 tries. + * - *resolve error* - when an error has occurred with a `resolve` + * + */ + StateService.prototype.go = function (to, params, options) { + var defautGoOpts = { relative: this.$current, inherit: true }; + var transOpts = common_1.defaults(options, defautGoOpts, transitionService_1.defaultTransOpts); + return this.transitionTo(to, params, transOpts); + }; + ; + /** Factory method for creating a TargetState */ + StateService.prototype.target = function (identifier, params, options) { + if (options === void 0) { options = {}; } + // If we're reloading, find the state object to reload from + if (predicates_1.isObject(options.reload) && !options.reload.name) + throw new Error('Invalid reload state object'); + options.reloadState = options.reload === true ? this.stateRegistry.root() : this.stateRegistry.matcher.find(options.reload, options.relative); + if (options.reload && !options.reloadState) + throw new Error("No such reload state '" + (predicates_1.isString(options.reload) ? options.reload : options.reload.name) + "'"); + var stateDefinition = this.stateRegistry.matcher.find(identifier, options.relative); + return new targetState_1.TargetState(identifier, stateDefinition, params, options); + }; + ; + /** + * @ngdoc function + * @name ui.router.state.$state#transitionTo + * @methodOf ui.router.state.$state + * + * @description + * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go} + * uses `transitionTo` internally. `$state.go` is recommended in most situations. + * + * @example + *
+	     * let app = angular.module('app', ['ui.router']);
+	     *
+	     * app.controller('ctrl', function ($scope, $state) {
+	     *   $scope.changeState = function () {
+	     *     $state.transitionTo('contact.detail');
+	     *   };
+	     * });
+	     * 
+ * + * @param {string} to State name. + * @param {object=} toParams A map of the parameters that will be sent to the state, + * will populate $stateParams. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params + * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd + * use this when you want to force a reload when *everything* is the same, including search params. + * + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + StateService.prototype.transitionTo = function (to, toParams, options) { + var _this = this; + if (toParams === void 0) { toParams = {}; } + if (options === void 0) { options = {}; } + var transHistory = this.globals.transitionHistory; + options = common_1.defaults(options, transitionService_1.defaultTransOpts); + options = common_1.extend(options, { current: transHistory.peekTail.bind(transHistory) }); + var ref = this.target(to, toParams, options); + var latestSuccess = this.globals.successfulTransitions.peekTail(); + var rootPath = function () { return pathFactory_1.PathFactory.bindTransNodesToPath([new node_1.Node(_this.stateRegistry.root())]); }; + var currentPath = latestSuccess ? latestSuccess.treeChanges().to : rootPath(); + if (!ref.exists()) + return this._handleInvalidTargetState(currentPath, ref); + if (!ref.valid()) + return coreservices_1.services.$q.reject(ref.error()); + var transition = this.$transitions.create(currentPath, ref); + var tMgr = new transitionManager_1.TransitionManager(transition, this.$transitions, this.$urlRouter, this.$view, this, this.globals); + var transitionPromise = tMgr.runTransition(); + // Return a promise for the transition, which also has the transition object on it. + return common_1.extend(transitionPromise, { transition: transition }); + }; + ; + /** + * @ngdoc function + * @name ui.router.state.$state#is + * @methodOf ui.router.state.$state + * + * @description + * Similar to {@link ui.router.state.$state#methods_includes $state.includes}, + * but only checks for the full state name. If params is supplied then it will be + * tested for strict equality against the current active params object, so all params + * must match with none missing and no extras. + * + * @example + *
+	     * $state.$current.name = 'contacts.details.item';
+	     *
+	     * // absolute name
+	     * $state.is('contact.details.item'); // returns true
+	     * $state.is(contactDetailItemStateObject); // returns true
+	     *
+	     * // relative name (. and ^), typically from a template
+	     * // E.g. from the 'contacts.details' template
+	     * 
Item
+ *
+ * + * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like + * to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will + * test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it is the state. + */ + StateService.prototype.is = function (stateOrName, params, options) { + options = common_1.defaults(options, { relative: this.$current }); + var state = this.stateRegistry.matcher.find(stateOrName, options.relative); + if (!predicates_1.isDefined(state)) + return undefined; + if (this.$current !== state) + return false; + return predicates_1.isDefined(params) && params !== null ? param_1.Param.equals(state.parameters(), this.params, params) : true; + }; + ; + /** + * @ngdoc function + * @name ui.router.state.$state#includes + * @methodOf ui.router.state.$state + * + * @description + * A method to determine if the current active state is equal to or is the child of the + * state stateName. If any params are passed then they will be tested for a match as well. + * Not all the parameters need to be passed, just the ones you'd like to test for equality. + * + * @example + * Partial and relative names + *
+	     * $state.$current.name = 'contacts.details.item';
+	     *
+	     * // Using partial names
+	     * $state.includes("contacts"); // returns true
+	     * $state.includes("contacts.details"); // returns true
+	     * $state.includes("contacts.details.item"); // returns true
+	     * $state.includes("contacts.list"); // returns false
+	     * $state.includes("about"); // returns false
+	     *
+	     * // Using relative names (. and ^), typically from a template
+	     * // E.g. from the 'contacts.details' template
+	     * 
Item
+ *
+ * + * Basic globbing patterns + *
+	     * $state.$current.name = 'contacts.details.item.url';
+	     *
+	     * $state.includes("*.details.*.*"); // returns true
+	     * $state.includes("*.details.**"); // returns true
+	     * $state.includes("**.item.**"); // returns true
+	     * $state.includes("*.details.item.url"); // returns true
+	     * $state.includes("*.details.*.url"); // returns true
+	     * $state.includes("*.details.*"); // returns false
+	     * $state.includes("item.**"); // returns false
+	     * 
+ * + * @param {string} stateOrName A partial name, relative name, or glob pattern + * to be searched for within the current state name. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, + * that you'd like to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set, + * .includes will test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it does include the state + */ + StateService.prototype.includes = function (stateOrName, params, options) { + options = common_1.defaults(options, { relative: this.$current }); + var glob = predicates_1.isString(stateOrName) && glob_1.Glob.fromString(stateOrName); + if (glob) { + if (!glob.matches(this.$current.name)) + return false; + stateOrName = this.$current.name; + } + var state = this.stateRegistry.matcher.find(stateOrName, options.relative), include = this.$current.includes; + if (!predicates_1.isDefined(state)) + return undefined; + if (!predicates_1.isDefined(include[state.name])) + return false; + // @TODO Replace with Param.equals() ? + return params ? common_2.equalForKeys(param_1.Param.values(state.parameters(), params), this.params, Object.keys(params)) : true; + }; + ; + /** + * @ngdoc function + * @name ui.router.state.$state#href + * @methodOf ui.router.state.$state + * + * @description + * A url generation method that returns the compiled url for the given state populated with the given params. + * + * @example + *
+	     * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
+	     * 
+ * + * @param {string|object} stateOrName The state name or state object you'd like to generate a url from. + * @param {object=} params An object of parameter values to fill the state's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the + * first parameter, then the constructed href url will be built from the first navigable ancestor (aka + * ancestor with a valid url). + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} compiled state url + */ + StateService.prototype.href = function (stateOrName, params, options) { + var defaultHrefOpts = { + lossy: true, + inherit: true, + absolute: false, + relative: this.$current + }; + options = common_1.defaults(options, defaultHrefOpts); + var state = this.stateRegistry.matcher.find(stateOrName, options.relative); + if (!predicates_1.isDefined(state)) + return null; + if (options.inherit) + params = this.params.$inherit(params || {}, this.$current, state); + var nav = (state && options.lossy) ? state.navigable : state; + if (!nav || nav.url === undefined || nav.url === null) { + return null; + } + return this.$urlRouter.href(nav.url, param_1.Param.values(state.parameters(), params), { + absolute: options.absolute + }); + }; + ; + StateService.prototype.get = function (stateOrName, base) { + if (arguments.length === 0) + return this.stateRegistry.get(); + return this.stateRegistry.get(stateOrName, base || this.$current); + }; + return StateService; + }()); + exports.StateService = StateService; + + +/***/ }, +/* 38 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module path */ /** for typedoc */ + "use strict"; + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var module_1 = __webpack_require__(17); + var node_1 = __webpack_require__(39); + var module_2 = __webpack_require__(40); + /** + * This class contains functions which convert TargetStates, Nodes and paths from one type to another. + */ + var PathFactory = (function () { + function PathFactory() { + } + /** Given a Node[], create an TargetState */ + PathFactory.makeTargetState = function (path) { + var state = common_1.tail(path).state; + return new module_1.TargetState(state, state, path.map(hof_1.prop("paramValues")).reduce(common_1.mergeR, {})); + }; + PathFactory.buildPath = function (targetState) { + var toParams = targetState.params(); + return targetState.$state().path.map(function (state) { return new node_1.Node(state).applyRawParams(toParams); }); + }; + /** Given a fromPath: Node[] and a TargetState, builds a toPath: Node[] */ + PathFactory.buildToPath = function (fromPath, targetState) { + var toPath = PathFactory.buildPath(targetState); + if (targetState.options().inherit) { + return PathFactory.inheritParams(fromPath, toPath, Object.keys(targetState.params())); + } + return toPath; + }; + PathFactory.applyViewConfigs = function ($view, path) { + return path.map(function (node) { + return common_1.extend(node, { views: common_1.values(node.state.views || {}).map(function (view) { return $view.createViewConfig(node, view); }) }); + }); + }; + /** + * Given a fromPath and a toPath, returns a new to path which inherits parameters from the fromPath + * + * For a parameter in a node to be inherited from the from path: + * - The toPath's node must have a matching node in the fromPath (by state). + * - The parameter name must not be found in the toKeys parameter array. + * + * Note: the keys provided in toKeys are intended to be those param keys explicitly specified by some + * caller, for instance, $state.transitionTo(..., toParams). If a key was found in toParams, + * it is not inherited from the fromPath. + */ + PathFactory.inheritParams = function (fromPath, toPath, toKeys) { + if (toKeys === void 0) { toKeys = []; } + function nodeParamVals(path, state) { + var node = common_1.find(path, hof_1.propEq('state', state)); + return common_1.extend({}, node && node.paramValues); + } + /** + * Given an Node "toNode", return a new Node with param values inherited from the + * matching node in fromPath. Only inherit keys that aren't found in "toKeys" from the node in "fromPath"" + */ + var makeInheritedParamsNode = hof_1.curry(function (_fromPath, _toKeys, toNode) { + // All param values for the node (may include default key/vals, when key was not found in toParams) + var toParamVals = common_1.extend({}, toNode && toNode.paramValues); + // limited to only those keys found in toParams + var incomingParamVals = common_1.pick(toParamVals, _toKeys); + toParamVals = common_1.omit(toParamVals, _toKeys); + var fromParamVals = nodeParamVals(_fromPath, toNode.state) || {}; + // extend toParamVals with any fromParamVals, then override any of those those with incomingParamVals + var ownParamVals = common_1.extend(toParamVals, fromParamVals, incomingParamVals); + return new node_1.Node(toNode.state).applyRawParams(ownParamVals); + }); + // The param keys specified by the incoming toParams + return toPath.map(makeInheritedParamsNode(fromPath, toKeys)); + }; + /** + * Given a path, upgrades the path to a Node[]. Each node is assigned a ResolveContext + * and ParamValues object which is bound to the whole path, but closes over the subpath from root to the node. + * The views are also added to the node. + */ + PathFactory.bindTransNodesToPath = function (resolvePath) { + var resolveContext = new module_2.ResolveContext(resolvePath); + // let paramValues = new ParamValues(resolvePath); + // Attach bound resolveContext and paramValues to each node + // Attach views to each node + resolvePath.forEach(function (node) { + node.resolveContext = resolveContext.isolateRootTo(node.state); + node.resolveInjector = new module_2.ResolveInjector(node.resolveContext, node.state); + node.resolves['$stateParams'] = new module_2.Resolvable("$stateParams", function () { return node.paramValues; }, node.paramValues); + }); + return resolvePath; + }; + /** + * Computes the tree changes (entering, exiting) between a fromPath and toPath. + */ + PathFactory.treeChanges = function (fromPath, toPath, reloadState) { + var keep = 0, max = Math.min(fromPath.length, toPath.length); + var staticParams = function (state) { return state.parameters({ inherit: false }).filter(hof_1.not(hof_1.prop('dynamic'))).map(hof_1.prop('id')); }; + var nodesMatch = function (node1, node2) { return node1.equals(node2, staticParams(node1.state)); }; + while (keep < max && fromPath[keep].state !== reloadState && nodesMatch(fromPath[keep], toPath[keep])) { + keep++; + } + /** Given a retained node, return a new node which uses the to node's param values */ + function applyToParams(retainedNode, idx) { + var cloned = node_1.Node.clone(retainedNode); + cloned.paramValues = toPath[idx].paramValues; + return cloned; + } + var from, retained, exiting, entering, to; + // intermediate vars + var retainedWithToParams, enteringResolvePath, toResolvePath; + from = fromPath; + retained = from.slice(0, keep); + exiting = from.slice(keep); + // Create a new retained path (with shallow copies of nodes) which have the params of the toPath mapped + retainedWithToParams = retained.map(applyToParams); + enteringResolvePath = toPath.slice(keep); + // "toResolvePath" is "retainedWithToParams" concat "enteringResolvePath". + toResolvePath = (retainedWithToParams).concat(enteringResolvePath); + // "to: is "toResolvePath" with ParamValues/ResolveContext added to each node and bound to the path context + to = PathFactory.bindTransNodesToPath(toResolvePath); + // "entering" is the tail of "to" + entering = to.slice(keep); + return { from: from, to: to, retained: retained, exiting: exiting, entering: entering }; + }; + PathFactory.bindTransitionResolve = function (treeChanges, transition) { + var rootNode = treeChanges.to[0]; + rootNode.resolves['$transition$'] = new module_2.Resolvable('$transition$', function () { return transition; }, transition); + }; + /** + * Find a subpath of a path that stops at the node for a given state + * + * Given an array of nodes, returns a subset of the array starting from the first node, up to the + * node whose state matches `stateName` + * + * @param path a path of [[Node]]s + * @param state the [[State]] to stop at + */ + PathFactory.subPath = function (path, state) { + var node = common_1.find(path, function (_node) { return _node.state === state; }); + var elementIdx = path.indexOf(node); + if (elementIdx === -1) + throw new Error("The path does not contain the state: " + state); + return path.slice(0, elementIdx + 1); + }; + /** Gets the raw parameter values from a path */ + PathFactory.paramValues = function (path) { return path.reduce(function (acc, node) { return common_1.extend(acc, node.paramValues); }, {}); }; + return PathFactory; + }()); + exports.PathFactory = PathFactory; + + +/***/ }, +/* 39 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module path */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var module_1 = __webpack_require__(40); + var Node = (function () { + function Node(state) { + if (state instanceof Node) { + var node = state; + this.state = node.state; + this.paramSchema = node.paramSchema.slice(); + this.paramValues = common_1.extend({}, node.paramValues); + this.resolves = common_1.extend({}, node.resolves); + this.views = node.views && node.views.slice(); + this.resolveContext = node.resolveContext; + this.resolveInjector = node.resolveInjector; + } + else { + this.state = state; + this.paramSchema = state.parameters({ inherit: false }); + this.paramValues = {}; + this.resolves = common_1.mapObj(state.resolve, function (fn, name) { return new module_1.Resolvable(name, fn); }); + } + } + Node.prototype.applyRawParams = function (params) { + var getParamVal = function (paramDef) { return [paramDef.id, paramDef.value(params[paramDef.id])]; }; + this.paramValues = this.paramSchema.reduce(function (memo, pDef) { return common_1.applyPairs(memo, getParamVal(pDef)); }, {}); + return this; + }; + Node.prototype.parameter = function (name) { + return common_1.find(this.paramSchema, hof_1.propEq("id", name)); + }; + Node.prototype.equals = function (node, keys) { + var _this = this; + if (keys === void 0) { keys = this.paramSchema.map(hof_1.prop('id')); } + var paramValsEq = function (key) { return _this.parameter(key).type.equals(_this.paramValues[key], node.paramValues[key]); }; + return this.state === node.state && keys.map(paramValsEq).reduce(common_1.allTrueR, true); + }; + Node.clone = function (node) { + return new Node(node); + }; + /** + * Returns a new path which is a subpath of the first path. The new path starts from root and contains any nodes + * that match the nodes in the second path. Nodes are compared using their state property. + * @param first {Node[]} + * @param second {Node[]} + * @returns {Node[]} + */ + Node.matching = function (first, second) { + var matchedCount = first.reduce(function (prev, node, i) { + return prev === i && i < second.length && node.state === second[i].state ? i + 1 : prev; + }, 0); + return first.slice(0, matchedCount); + }; + return Node; + }()); + exports.Node = Node; + + +/***/ }, +/* 40 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** @module resolve */ /** for typedoc */ + __export(__webpack_require__(31)); + __export(__webpack_require__(32)); + __export(__webpack_require__(41)); + __export(__webpack_require__(42)); + + +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module resolve */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var predicates_1 = __webpack_require__(4); + var trace_1 = __webpack_require__(12); + var coreservices_1 = __webpack_require__(6); + var interface_1 = __webpack_require__(31); + var common_2 = __webpack_require__(3); + var pathFactory_1 = __webpack_require__(38); + // TODO: make this configurable + var defaultResolvePolicy = interface_1.ResolvePolicy[interface_1.ResolvePolicy.LAZY]; + var ResolveContext = (function () { + function ResolveContext(_path) { + this._path = _path; + common_1.extend(this, { + _nodeFor: function (state) { + return common_1.find(this._path, hof_1.propEq('state', state)); + }, + _pathTo: function (state) { + return pathFactory_1.PathFactory.subPath(this._path, state); + } + }); + } + /** + * Gets the available Resolvables for the last element of this path. + * + * @param state the State (within the ResolveContext's Path) for which to get resolvables + * @param options + * + * options.omitOwnLocals: array of property names + * Omits those Resolvables which are found on the last element of the path. + * + * This will hide a deepest-level resolvable (by name), potentially exposing a parent resolvable of + * the same name further up the state tree. + * + * This is used by Resolvable.resolve() in order to provide the Resolvable access to all the other + * Resolvables at its own PathElement level, yet disallow that Resolvable access to its own injectable Resolvable. + * + * This is also used to allow a state to override a parent state's resolve while also injecting + * that parent state's resolve: + * + * state({ name: 'G', resolve: { _G: function() { return "G"; } } }); + * state({ name: 'G.G2', resolve: { _G: function(_G) { return _G + "G2"; } } }); + * where injecting _G into a controller will yield "GG2" + */ + ResolveContext.prototype.getResolvables = function (state, options) { + options = common_1.defaults(options, { omitOwnLocals: [] }); + var path = (state ? this._pathTo(state) : this._path); + var last = common_1.tail(path); + return path.reduce(function (memo, node) { + var omitProps = (node === last) ? options.omitOwnLocals : []; + var filteredResolvables = common_1.omit(node.resolves, omitProps); + return common_1.extend(memo, filteredResolvables); + }, {}); + }; + /** Inspects a function `fn` for its dependencies. Returns an object containing any matching Resolvables */ + ResolveContext.prototype.getResolvablesForFn = function (fn) { + var deps = coreservices_1.services.$injector.annotate(fn, coreservices_1.services.$injector.strictDi); + return common_1.pick(this.getResolvables(), deps); + }; + ResolveContext.prototype.isolateRootTo = function (state) { + return new ResolveContext(this._pathTo(state)); + }; + ResolveContext.prototype.addResolvables = function (resolvables, state) { + common_1.extend(this._nodeFor(state).resolves, resolvables); + }; + /** Gets the resolvables declared on a particular state */ + ResolveContext.prototype.getOwnResolvables = function (state) { + return common_1.extend({}, this._nodeFor(state).resolves); + }; + // Returns a promise for an array of resolved path Element promises + ResolveContext.prototype.resolvePath = function (options) { + var _this = this; + if (options === void 0) { options = {}; } + trace_1.trace.traceResolvePath(this._path, options); + var promiseForNode = function (node) { return _this.resolvePathElement(node.state, options); }; + return coreservices_1.services.$q.all(common_1.map(this._path, promiseForNode)).then(function (all) { return all.reduce(common_2.mergeR, {}); }); + }; + // returns a promise for all the resolvables on this PathElement + // options.resolvePolicy: only return promises for those Resolvables which are at + // the specified policy, or above. i.e., options.resolvePolicy === 'lazy' will + // resolve both 'lazy' and 'eager' resolves. + ResolveContext.prototype.resolvePathElement = function (state, options) { + var _this = this; + if (options === void 0) { options = {}; } + // The caller can request the path be resolved for a given policy and "below" + var policy = options && options.resolvePolicy; + var policyOrdinal = interface_1.ResolvePolicy[policy || defaultResolvePolicy]; + // Get path Resolvables available to this element + var resolvables = this.getOwnResolvables(state); + var matchesRequestedPolicy = function (resolvable) { return getPolicy(state.resolvePolicy, resolvable) >= policyOrdinal; }; + var matchingResolves = common_1.filter(resolvables, matchesRequestedPolicy); + var getResolvePromise = function (resolvable) { return resolvable.get(_this.isolateRootTo(state), options); }; + var resolvablePromises = common_1.map(matchingResolves, getResolvePromise); + trace_1.trace.traceResolvePathElement(this, matchingResolves, options); + return coreservices_1.services.$q.all(resolvablePromises); + }; + /** + * Injects a function given the Resolvables available in the path, from the first node + * up to the node for the given state. + * + * First it resolves all the resolvable depencies. When they are done resolving, it invokes + * the function. + * + * @return a promise for the return value of the function. + * + * @param fn: the function to inject (i.e., onEnter, onExit, controller) + * @param locals: are the angular $injector-style locals to inject + * @param options: options (TODO: document) + */ + ResolveContext.prototype.invokeLater = function (fn, locals, options) { + var _this = this; + if (locals === void 0) { locals = {}; } + if (options === void 0) { options = {}; } + var resolvables = this.getResolvablesForFn(fn); + trace_1.trace.tracePathElementInvoke(common_1.tail(this._path), fn, Object.keys(resolvables), common_1.extend({ when: "Later" }, options)); + var getPromise = function (resolvable) { return resolvable.get(_this, options); }; + var promises = common_1.map(resolvables, getPromise); + return coreservices_1.services.$q.all(promises).then(function () { + try { + return _this.invokeNow(fn, locals, options); + } + catch (error) { + return coreservices_1.services.$q.reject(error); + } + }); + }; + /** + * Immediately injects a function with the dependent Resolvables available in the path, from + * the first node up to the node for the given state. + * + * If a Resolvable is not yet resolved, then null is injected in place of the resolvable. + * + * @return the return value of the function. + * + * @param fn: the function to inject (i.e., onEnter, onExit, controller) + * @param locals: are the angular $injector-style locals to inject + * @param options: options (TODO: document) + */ + // Injects a function at this PathElement level with available Resolvables + // Does not wait until all Resolvables have been resolved; you must call PathElement.resolve() (or manually resolve each dep) first + ResolveContext.prototype.invokeNow = function (fn, locals, options) { + if (options === void 0) { options = {}; } + var resolvables = this.getResolvablesForFn(fn); + trace_1.trace.tracePathElementInvoke(common_1.tail(this._path), fn, Object.keys(resolvables), common_1.extend({ when: "Now " }, options)); + var resolvedLocals = common_1.map(resolvables, hof_1.prop("data")); + return coreservices_1.services.$injector.invoke(fn, options.bind || null, common_1.extend({}, locals, resolvedLocals)); + }; + return ResolveContext; + }()); + exports.ResolveContext = ResolveContext; + /** + * Given a state's resolvePolicy attribute and a resolvable from that state, returns the policy ordinal for the Resolvable + * Use the policy declared for the Resolve. If undefined, use the policy declared for the State. If + * undefined, use the system defaultResolvePolicy. + * + * @param stateResolvePolicyConf The raw resolvePolicy declaration on the state object; may be a String or Object + * @param resolvable The resolvable to compute the policy for + */ + function getPolicy(stateResolvePolicyConf, resolvable) { + // Normalize the configuration on the state to either state-level (a string) or resolve-level (a Map of string:string) + var stateLevelPolicy = (predicates_1.isString(stateResolvePolicyConf) ? stateResolvePolicyConf : null); + var resolveLevelPolicies = (predicates_1.isObject(stateResolvePolicyConf) ? stateResolvePolicyConf : {}); + var policyName = resolveLevelPolicies[resolvable.name] || stateLevelPolicy || defaultResolvePolicy; + return interface_1.ResolvePolicy[policyName]; + } + + +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module resolve */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var ResolveInjector = (function () { + function ResolveInjector(_resolveContext, _state) { + this._resolveContext = _resolveContext; + this._state = _state; + } + /** Returns a promise to invoke an annotated function in the resolve context */ + ResolveInjector.prototype.invokeLater = function (injectedFn, locals) { + return this._resolveContext.invokeLater(injectedFn, locals); + }; + /** Invokes an annotated function in the resolve context */ + ResolveInjector.prototype.invokeNow = function (injectedFn, locals) { + return this._resolveContext.invokeNow(null, injectedFn, locals); + }; + /** Returns the a promise for locals (realized Resolvables) that a function wants */ + ResolveInjector.prototype.getLocals = function (injectedFn) { + var _this = this; + var resolve = function (r) { return r.get(_this._resolveContext); }; + return common_1.map(this._resolveContext.getResolvablesForFn(injectedFn), resolve); + }; + return ResolveInjector; + }()); + exports.ResolveInjector = ResolveInjector; + + +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + var transition_1 = __webpack_require__(11); + var hookRegistry_1 = __webpack_require__(15); + /** + * The default transition options. + * Include this object when applying custom defaults: + * let reloadOpts = { reload: true, notify: true } + * let options = defaults(theirOpts, customDefaults, defaultOptions); + */ + exports.defaultTransOpts = { + location: true, + relative: null, + inherit: false, + notify: true, + reload: false, + custom: {}, + current: function () { return null; } + }; + /** + * This class provides services related to Transitions. + * + * Most importantly, it allows global Transition Hooks to be registered, and has a factory function + * for creating new Transitions. + */ + var TransitionService = (function () { + function TransitionService($view) { + this.$view = $view; + this._defaultErrorHandler = function $defaultErrorHandler($error$) { + if ($error$ instanceof Error) { + console.error($error$); + } + }; + hookRegistry_1.HookRegistry.mixin(new hookRegistry_1.HookRegistry(), this); + } + TransitionService.prototype.defaultErrorHandler = function (handler) { + return this._defaultErrorHandler = handler || this._defaultErrorHandler; + }; + /** + * Creates a new [[Transition]] object + * + * This is a factory function for creating new Transition objects. + * + * @param fromPath + * @param targetState + * @returns {Transition} + */ + TransitionService.prototype.create = function (fromPath, targetState) { + return new transition_1.Transition(fromPath, targetState, this); + }; + return TransitionService; + }()); + exports.TransitionService = TransitionService; + + +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** @module path */ /** for typedoc */ + __export(__webpack_require__(39)); + __export(__webpack_require__(38)); + + +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** @module url */ /** for typedoc */ + __export(__webpack_require__(46)); + __export(__webpack_require__(22)); + __export(__webpack_require__(47)); + __export(__webpack_require__(48)); + + +/***/ }, +/* 46 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module url */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var predicates_1 = __webpack_require__(4); + var module_1 = __webpack_require__(20); + var predicates_2 = __webpack_require__(4); + var param_1 = __webpack_require__(21); + var common_2 = __webpack_require__(3); + var common_3 = __webpack_require__(3); + function quoteRegExp(string, param) { + var surroundPattern = ['', ''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&"); + if (!param) + return result; + switch (param.squash) { + case false: + surroundPattern = ['(', ')' + (param.isOptional ? '?' : '')]; + break; + case true: + result = result.replace(/\/$/, ''); + surroundPattern = ['(?:\/(', ')|\/)?']; + break; + default: + surroundPattern = [("(" + param.squash + "|"), ')?']; + break; + } + return result + surroundPattern[0] + param.type.pattern.source + surroundPattern[1]; + } + var memoizeTo = function (obj, prop, fn) { return obj[prop] = obj[prop] || fn(); }; + /** + * @ngdoc object + * @name ui.router.util.type:UrlMatcher + * + * @description + * 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 ui.router.util.type:UrlMatcher#methods_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|type '}'` - curly placeholder with regexp or type name. 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. + * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined + * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start + * + * @param {string} pattern The pattern to compile into a matcher. + * @param {Object} config A configuration object hash + * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`. + * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`. + * + * @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 ui.router.util.type:UrlMatcher#methods_exec exec()} returns + * non-null) will start with this prefix. + * + * @property {string} pattern The pattern that was passed into the constructor + * + * @returns {Object} New `UrlMatcher` object + */ + var UrlMatcher = (function () { + function UrlMatcher(pattern, config) { + var _this = this; + this.pattern = pattern; + this.config = config; + this._cache = { path: [], pattern: null }; + this._children = []; + this._params = []; + this._segments = []; + this._compiled = []; + this.config = common_1.defaults(this.config, { + params: {}, + strict: true, + caseInsensitive: false, + paramMap: common_1.identity + }); + // 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) (search version has - for snake-case) + // \{([\w\[\]]+)(?:\:\s*( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case + // (?: ... | ... | ... )+ - 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\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, searchPlaceholder = /([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, last = 0, m, patterns = []; + var checkParamErrors = function (id) { + if (!UrlMatcher.nameValidator.test(id)) + throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'"); + if (common_1.find(_this._params, hof_1.propEq('id', id))) + throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'"); + }; + // Split into static segments separated by path parameter placeholders. + // The number of segments is always 1 more than the number of parameters. + var matchDetails = function (m, isSearch) { + // IE[78] returns '' for unmatched groups instead of null + var id = m[2] || m[3], regexp = isSearch ? m[4] : m[4] || (m[1] === '*' ? '.*' : null); + return { + id: id, + regexp: regexp, + cfg: _this.config.params[id], + segment: pattern.substring(last, m.index), + type: !regexp ? null : module_1.paramTypes.type(regexp || "string") || common_1.inherit(module_1.paramTypes.type("string"), { + pattern: new RegExp(regexp, _this.config.caseInsensitive ? 'i' : undefined) + }) + }; + }; + var p, segment; + while ((m = placeholder.exec(pattern))) { + p = matchDetails(m, false); + if (p.segment.indexOf('?') >= 0) + break; // we're into the search part + checkParamErrors(p.id); + this._params.push(module_1.Param.fromPath(p.id, p.type, this.config.paramMap(p.cfg, false))); + this._segments.push(p.segment); + patterns.push([p.segment, common_1.tail(this._params)]); + 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 = segment.substring(i); + segment = segment.substring(0, i); + if (search.length > 0) { + last = 0; + while ((m = searchPlaceholder.exec(search))) { + p = matchDetails(m, true); + checkParamErrors(p.id); + this._params.push(module_1.Param.fromSearch(p.id, p.type, this.config.paramMap(p.cfg, true))); + last = placeholder.lastIndex; + } + } + } + this._segments.push(segment); + common_1.extend(this, { + _compiled: patterns.map(function (pattern) { return quoteRegExp.apply(null, pattern); }).concat(quoteRegExp(segment)), + prefix: this._segments[0] + }); + Object.freeze(this); + } + /** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#append + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * @TODO + * + * @example + * @TODO + * + * @param {UrlMatcher} url A `UrlMatcher` instance to append as a child of the current `UrlMatcher`. + */ + UrlMatcher.prototype.append = function (url) { + this._children.push(url); + common_1.forEach(url._cache, function (val, key) { return url._cache[key] = predicates_1.isArray(val) ? [] : null; }); + url._cache.path = this._cache.path.concat(this); + return url; + }; + UrlMatcher.prototype.isRoot = function () { + return this._cache.path.length === 0; + }; + UrlMatcher.prototype.toString = function () { + return this.pattern; + }; + /** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#exec + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * 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 `search`. 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} search URL search parameters, e.g. `$location.search()`. + * @param {string} hash URL hash e.g. `$location.hash()`. + * @param {Object} options + * @returns {Object} The captured parameter values. + */ + UrlMatcher.prototype.exec = function (path, search, hash, options) { + var _this = this; + if (search === void 0) { search = {}; } + if (options === void 0) { options = {}; } + var match = memoizeTo(this._cache, 'pattern', function () { + return new RegExp([ + '^', + common_1.unnest(_this._cache.path.concat(_this).map(hof_1.prop('_compiled'))).join(''), + _this.config.strict === false ? '\/?' : '', + '$' + ].join(''), _this.config.caseInsensitive ? 'i' : undefined); + }).exec(path); + if (!match) + return null; + //options = defaults(options, { isolate: false }); + var allParams = this.parameters(), pathParams = allParams.filter(function (param) { return !param.isSearch(); }), searchParams = allParams.filter(function (param) { return param.isSearch(); }), nPathSegments = this._cache.path.concat(this).map(function (urlm) { return urlm._segments.length - 1; }).reduce(function (a, x) { return a + x; }), values = {}; + if (nPathSegments !== match.length - 1) + throw new Error("Unbalanced capture group in route '" + this.pattern + "'"); + function decodePathArray(string) { + var reverseString = function (str) { return str.split("").reverse().join(""); }; + var unquoteDashes = function (str) { return str.replace(/\\-/g, "-"); }; + var split = reverseString(string).split(/-(?!\\)/); + var allReversed = common_1.map(split, reverseString); + return common_1.map(allReversed, unquoteDashes).reverse(); + } + for (var i = 0; i < nPathSegments; i++) { + var param = pathParams[i]; + var value = match[i + 1]; + // if the param value matches a pre-replace pair, replace the value before decoding. + for (var j = 0; j < param.replace.length; j++) { + if (param.replace[j].from === value) + value = param.replace[j].to; + } + if (value && param.array === true) + value = decodePathArray(value); + if (predicates_2.isDefined(value)) + value = param.type.decode(value); + values[param.id] = param.value(value); + } + common_1.forEach(searchParams, function (param) { + var value = search[param.id]; + for (var j = 0; j < param.replace.length; j++) { + if (param.replace[j].from === value) + value = param.replace[j].to; + } + if (predicates_2.isDefined(value)) + value = param.type.decode(value); + values[param.id] = param.value(value); + }); + if (hash) + values["#"] = hash; + return values; + }; + /** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#parameters + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Returns the names of all path and search parameters of this pattern in order of appearance. + * + * @returns {Array.} An array of [[Param]] objects. Must be treated as read-only. If the + * pattern has no parameters, an empty array is returned. + */ + UrlMatcher.prototype.parameters = function (opts) { + if (opts === void 0) { opts = {}; } + if (opts.inherit === false) + return this._params; + return common_1.unnest(this._cache.path.concat(this).map(hof_1.prop('_params'))); + }; + UrlMatcher.prototype.parameter = function (id, opts) { + if (opts === void 0) { opts = {}; } + var parent = common_1.tail(this._cache.path); + return (common_1.find(this._params, hof_1.propEq('id', id)) || + (opts.inherit !== false && parent && parent.parameter(id)) || + null); + }; + /** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#validates + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Checks an object hash of parameters to validate their correctness according to the parameter + * types of this `UrlMatcher`. + * + * @param {Object} params The object hash of parameters to validate. + * @returns {boolean} Returns `true` if `params` validates, otherwise `false`. + */ + UrlMatcher.prototype.validates = function (params) { + var _this = this; + var validParamVal = function (param, val) { return !param || param.validates(val); }; + return common_1.pairs(params || {}).map(function (_a) { + var key = _a[0], val = _a[1]; + return validParamVal(_this.parameter(key), val); + }).reduce(common_1.allTrueR, true); + }; + /** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#format + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * 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. + * @returns {string} the formatted URL (path and optionally search part). + */ + UrlMatcher.prototype.format = function (values) { + if (values === void 0) { values = {}; } + if (!this.validates(values)) + return null; + // Build the full path of UrlMatchers (including all parent UrlMatchers) + var urlMatchers = this._cache.path.slice().concat(this); + // Extract all the static segments and Params into an ordered array + var pathSegmentsAndParams = urlMatchers.map(UrlMatcher.pathSegmentsAndParams).reduce(common_2.unnestR, []); + // Extract the query params into a separate array + var queryParams = urlMatchers.map(UrlMatcher.queryParams).reduce(common_2.unnestR, []); + /** + * Given a Param, + * Applies the parameter value, then returns details about it + */ + function getDetails(param) { + // Normalize to typed value + var value = param.value(values[param.id]); + var isDefaultValue = param.isDefaultValue(value); + // Check if we're in squash mode for the parameter + var squash = isDefaultValue ? param.squash : false; + // Allow the Parameter's Type to encode the value + var encoded = param.type.encode(value); + return { param: param, value: value, isDefaultValue: isDefaultValue, squash: squash, encoded: encoded }; + } + // Build up the path-portion from the list of static segments and parameters + var pathString = pathSegmentsAndParams.reduce(function (acc, x) { + // The element is a static segment (a raw string); just append it + if (predicates_1.isString(x)) + return acc + x; + // Otherwise, it's a Param. Fetch details about the parameter value + var _a = getDetails(x), squash = _a.squash, encoded = _a.encoded, param = _a.param; + // If squash is === true, try to remove a slash from the path + if (squash === true) + return (acc.match(/\/$/)) ? acc.slice(0, -1) : acc; + // If squash is a string, use the string for the param value + if (predicates_1.isString(squash)) + return acc + squash; + if (squash !== false) + return acc; // ? + if (encoded == null) + return acc; + // If this parameter value is an array, encode the value using encodeDashes + if (predicates_1.isArray(encoded)) + return acc + common_1.map(encoded, UrlMatcher.encodeDashes).join("-"); + // If the parameter type is "raw", then do not encodeURIComponent + if (param.type.raw) + return acc + encoded; + // Encode the value + return acc + encodeURIComponent(encoded); + }, ""); + // Build the query string by applying parameter values (array or regular) + // then mapping to key=value, then flattening and joining using "&" + var queryString = queryParams.map(function (param) { + var _a = getDetails(param), squash = _a.squash, encoded = _a.encoded, isDefaultValue = _a.isDefaultValue; + if (encoded == null || (isDefaultValue && squash !== false)) + return; + if (!predicates_1.isArray(encoded)) + encoded = [encoded]; + if (encoded.length === 0) + return; + if (!param.type.raw) + encoded = common_1.map(encoded, encodeURIComponent); + return encoded.map(function (val) { return (param.id + "=" + val); }); + }).filter(common_1.identity).reduce(common_2.unnestR, []).join("&"); + // Concat the pathstring with the queryString (if exists) and the hashString (if exists) + return pathString + (queryString ? "?" + queryString : "") + (values["#"] ? "#" + values["#"] : ""); + }; + UrlMatcher.encodeDashes = function (str) { + return encodeURIComponent(str).replace(/-/g, function (c) { return ("%5C%" + c.charCodeAt(0).toString(16).toUpperCase()); }); + }; + /** Given a matcher, return an array with the matcher's path segments and path params, in order */ + UrlMatcher.pathSegmentsAndParams = function (matcher) { + var staticSegments = matcher._segments; + var pathParams = matcher._params.filter(function (p) { return p.location === param_1.DefType.PATH; }); + return common_3.arrayTuples(staticSegments, pathParams.concat(undefined)).reduce(common_2.unnestR, []).filter(function (x) { return x !== "" && predicates_2.isDefined(x); }); + }; + /** Given a matcher, return an array with the matcher's query params */ + UrlMatcher.queryParams = function (matcher) { + return matcher._params.filter(function (p) { return p.location === param_1.DefType.SEARCH; }); + }; + UrlMatcher.nameValidator = /^\w+([-.]+\w+)*(?:\[\])?$/; + return UrlMatcher; + }()); + exports.UrlMatcher = UrlMatcher; + + +/***/ }, +/* 47 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module url */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var module_1 = __webpack_require__(45); + var module_2 = __webpack_require__(20); + function getDefaultConfig() { + return { + strict: module_1.matcherConfig.strictMode(), + caseInsensitive: module_1.matcherConfig.caseInsensitive() + }; + } + /** + * Factory for [[UrlMatcher]] instances. + * + * The factory is available to ng1 services as + * `$urlMatcherFactor` or ng1 providers as `$urlMatcherFactoryProvider`. + */ + var UrlMatcherFactory = (function () { + function UrlMatcherFactory() { + common_1.extend(this, { UrlMatcher: module_1.UrlMatcher, Param: module_2.Param }); + } + /** + * Defines whether URL matching should be case sensitive (the default behavior), or not. + * + * @param value `false` to match URL in a case sensitive manner; otherwise `true`; + * @returns the current value of caseInsensitive + */ + UrlMatcherFactory.prototype.caseInsensitive = function (value) { + return module_1.matcherConfig.caseInsensitive(value); + }; + /** + * Defines whether URLs should match trailing slashes, or not (the default behavior). + * + * @param value `false` to match trailing slashes in URLs, otherwise `true`. + * @returns the current value of strictMode + */ + UrlMatcherFactory.prototype.strictMode = function (value) { + return module_1.matcherConfig.strictMode(value); + }; + /** + * Sets the default behavior when generating or matching URLs with default parameter values. + * + * @param value A string that defines the default parameter URL squashing behavior. + * - `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL + * - `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the + * parameter is surrounded by slashes, squash (remove) one slash from the URL + * - any other string, e.g. "~": When generating an href with a default parameter value, squash (remove) + * the parameter value from the URL and replace it with this string. + * @returns the current value of defaultSquashPolicy + */ + UrlMatcherFactory.prototype.defaultSquashPolicy = function (value) { + return module_1.matcherConfig.defaultSquashPolicy(value); + }; + /** + * Creates a [[UrlMatcher]] for the specified pattern. + * + * @param pattern The URL pattern. + * @param config The config object hash. + * @returns The UrlMatcher. + */ + UrlMatcherFactory.prototype.compile = function (pattern, config) { + return new module_1.UrlMatcher(pattern, common_1.extend(getDefaultConfig(), config)); + }; + /** + * Returns true if the specified object is a [[UrlMatcher]], or false otherwise. + * + * @param object The object to perform the type check against. + * @returns `true` if the object matches the `UrlMatcher` interface, by + * implementing all the same methods. + */ + UrlMatcherFactory.prototype.isMatcher = function (object) { + // TODO: typeof? + if (!predicates_1.isObject(object)) + return false; + var result = true; + common_1.forEach(module_1.UrlMatcher.prototype, function (val, name) { + if (predicates_1.isFunction(val)) + result = result && (predicates_1.isDefined(object[name]) && predicates_1.isFunction(object[name])); + }); + return result; + }; + ; + /** + * Registers a custom [[Type]] object that can be used to generate URLs with typed parameters. + * + * @param name The type name. + * @param definition The type definition. See [[Type]] for information on the values accepted. + * @param definitionFn A function that is injected before the app + * runtime starts. The result of this function is merged into the existing `definition`. + * See [[Type]] for information on the values accepted. + * + * @returns - if a type was registered: the [[UrlMatcherFactory]] + * - if only the `name` parameter was specified: the currently registered [[Type]] object, or undefined + * + * --- + * + * This is a simple example of a custom type that encodes and decodes items from an + * array, using the array index as the URL-encoded value: + * + * @example + * ``` + * + * var list = ['John', 'Paul', 'George', 'Ringo']; + * + * $urlMatcherFactoryProvider.type('listItem', { + * encode: function(item) { + * // Represent the list item in the URL using its corresponding index + * return list.indexOf(item); + * }, + * decode: function(item) { + * // Look up the list item by index + * return list[parseInt(item, 10)]; + * }, + * is: function(item) { + * // Ensure the item is valid by checking to see that it appears + * // in the list + * return list.indexOf(item) > -1; + * } + * }); + * + * $stateProvider.state('list', { + * url: "/list/{item:listItem}", + * controller: function($scope, $stateParams) { + * console.log($stateParams.item); + * } + * }); + * + * // ... + * + * // Changes URL to '/list/3', logs "Ringo" to the console + * $state.go('list', { item: "Ringo" }); + * ``` + */ + UrlMatcherFactory.prototype.type = function (name, definition, definitionFn) { + var type = module_2.paramTypes.type(name, definition, definitionFn); + return !predicates_1.isDefined(definition) ? type : this; + }; + ; + /** @hidden */ + UrlMatcherFactory.prototype.$get = function () { + module_2.paramTypes.enqueue = false; + module_2.paramTypes._flushTypeQueue(); + return this; + }; + ; + return UrlMatcherFactory; + }()); + exports.UrlMatcherFactory = UrlMatcherFactory; + + +/***/ }, +/* 48 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module url */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var coreservices_1 = __webpack_require__(6); + var $location = coreservices_1.services.location; + // Returns a string that is a prefix of all strings matching the RegExp + function regExpPrefix(re) { + var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source); + return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : ''; + } + // Interpolates matched values into a String.replace()-style pattern + function interpolate(pattern, match) { + return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) { + return match[what === '$' ? 0 : Number(what)]; + }); + } + function handleIfMatch($injector, $stateParams, handler, match) { + if (!match) + return false; + var result = $injector.invoke(handler, handler, { $match: match, $stateParams: $stateParams }); + return predicates_1.isDefined(result) ? result : true; + } + function appendBasePath(url, isHtml5, absolute) { + var baseHref = coreservices_1.services.locationConfig.baseHref(); + if (baseHref === '/') + return url; + if (isHtml5) + return baseHref.slice(0, -1) + url; + if (absolute) + return baseHref.slice(1) + url; + return url; + } + // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree + function update(rules, otherwiseFn, evt) { + if (evt && evt.defaultPrevented) + return; + function check(rule) { + var handled = rule(coreservices_1.services.$injector, $location); + if (!handled) + return false; + if (predicates_1.isString(handled)) { + $location.replace(); + $location.url(handled); + } + return true; + } + var n = rules.length, i; + for (i = 0; i < n; i++) { + if (check(rules[i])) + return; + } + // always check otherwise last to allow dynamic updates to the set of rules + if (otherwiseFn) + check(otherwiseFn); + } + /** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider + * + * @requires ui.router.util.$urlMatcherFactoryProvider + * @requires $locationProvider + * + * @description + * `$urlRouterProvider` has the responsibility of watching `$location`. + * When `$location` changes it runs through a list of rules one by one until a + * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify + * a url in a state configuration. All urls are compiled into a UrlMatcher object. + * + * There are several methods on `$urlRouterProvider` that make it useful to use directly + * in your module config. + */ + var UrlRouterProvider = (function () { + function UrlRouterProvider($urlMatcherFactory, $stateParams) { + this.$urlMatcherFactory = $urlMatcherFactory; + this.$stateParams = $stateParams; + /** @hidden */ + this.rules = []; + /** @hidden */ + this.otherwiseFn = null; + /** @hidden */ + this.interceptDeferred = false; + } + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#rule + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines rules that are used by `$urlRouterProvider` to find matches for + * specific URLs. + * + * @example + *
+	     * var app = angular.module('app', ['ui.router.router']);
+	     *
+	     * app.config(function ($urlRouterProvider) {
+	     *   // Here's an example of how you might allow case insensitive urls
+	     *   $urlRouterProvider.rule(function ($injector, $location) {
+	     *     var path = $location.path(),
+	     *         normalized = path.toLowerCase();
+	     *
+	     *     if (path !== normalized) {
+	     *       return normalized;
+	     *     }
+	     *   });
+	     * });
+	     * 
+ * + * @param {function} rule Handler function that takes `$injector` and `$location` + * services as arguments. You can use them to return a valid path as a string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + UrlRouterProvider.prototype.rule = function (rule) { + if (!predicates_1.isFunction(rule)) + throw new Error("'rule' must be a function"); + this.rules.push(rule); + return this; + }; + ; + /** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider#otherwise + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines a path that is used when an invalid route is requested. + * + * @example + *
+	     * var app = angular.module('app', ['ui.router.router']);
+	     *
+	     * app.config(function ($urlRouterProvider) {
+	     *   // if the path doesn't match any of the urls you configured
+	     *   // otherwise will take care of routing the user to the
+	     *   // specified url
+	     *   $urlRouterProvider.otherwise('/index');
+	     *
+	     *   // Example of using function rule as param
+	     *   $urlRouterProvider.otherwise(function ($injector, $location) {
+	     *     return '/a/valid/url';
+	     *   });
+	     * });
+	     * 
+ * + * @param {string|function} rule The url path you want to redirect to or a function + * rule that returns the url path. The function version is passed two params: + * `$injector` and `$location` services, and must return a url string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + UrlRouterProvider.prototype.otherwise = function (rule) { + if (!predicates_1.isFunction(rule) && !predicates_1.isString(rule)) + throw new Error("'rule' must be a string or function"); + this.otherwiseFn = predicates_1.isString(rule) ? function () { return rule; } : rule; + return this; + }; + ; + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#when + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Registers a handler for a given url matching. + * + * If the handler is a string, it is + * treated as a redirect, and is interpolated according to the syntax of match + * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise). + * + * If the handler is a function, it is injectable. It gets invoked if `$location` + * matches. You have the option of inject the match object as `$match`. + * + * The handler can return + * + * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter` + * will continue trying to find another one that matches. + * - **string** which is treated as a redirect and passed to `$location.url()` + * - **void** or any **truthy** value tells `$urlRouter` that the url was handled. + * + * @example + *
+	     * var app = angular.module('app', ['ui.router.router']);
+	     *
+	     * app.config(function ($urlRouterProvider) {
+	     *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
+	     *     if ($state.$current.navigable !== state ||
+	     *         !equalForKeys($match, $stateParams) {
+	     *      $state.transitionTo(state, $match, false);
+	     *     }
+	     *   });
+	     * });
+	     * 
+ * + * @param {string|object} what The incoming path that you want to redirect. + * @param {string|function} handler The path you want to redirect your user to. + */ + UrlRouterProvider.prototype.when = function (what, handler) { + var _a = this, $urlMatcherFactory = _a.$urlMatcherFactory, $stateParams = _a.$stateParams; + var redirect, handlerIsString = predicates_1.isString(handler); + // @todo Queue this + if (predicates_1.isString(what)) + what = $urlMatcherFactory.compile(what); + if (!handlerIsString && !predicates_1.isFunction(handler) && !predicates_1.isArray(handler)) + throw new Error("invalid 'handler' in when()"); + var strategies = { + matcher: function (_what, _handler) { + if (handlerIsString) { + redirect = $urlMatcherFactory.compile(_handler); + _handler = ['$match', redirect.format.bind(redirect)]; + } + return common_1.extend(function () { + return handleIfMatch(coreservices_1.services.$injector, $stateParams, _handler, _what.exec($location.path(), $location.search(), $location.hash())); + }, { + prefix: predicates_1.isString(_what.prefix) ? _what.prefix : '' + }); + }, + regex: function (_what, _handler) { + if (_what.global || _what.sticky) + throw new Error("when() RegExp must not be global or sticky"); + if (handlerIsString) { + redirect = _handler; + _handler = ['$match', function ($match) { return interpolate(redirect, $match); }]; + } + return common_1.extend(function () { + return handleIfMatch(coreservices_1.services.$injector, $stateParams, _handler, _what.exec($location.path())); + }, { + prefix: regExpPrefix(_what) + }); + } + }; + var check = { + matcher: $urlMatcherFactory.isMatcher(what), + regex: what instanceof RegExp + }; + for (var n in check) { + if (check[n]) + return this.rule(strategies[n](what, handler)); + } + throw new Error("invalid 'what' in when()"); + }; + ; + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#deferIntercept + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Disables (or enables) deferring location change interception. + * + * If you wish to customize the behavior of syncing the URL (for example, if you wish to + * defer a transition but maintain the current URL), call this method at configuration time. + * Then, at run time, call `$urlRouter.listen()` after you have configured your own + * `$locationChangeSuccess` event handler. + * + * @example + *
+	     * var app = angular.module('app', ['ui.router.router']);
+	     *
+	     * app.config(function ($urlRouterProvider) {
+	     *
+	     *   // Prevent $urlRouter from automatically intercepting URL changes;
+	     *   // this allows you to configure custom behavior in between
+	     *   // location changes and route synchronization:
+	     *   $urlRouterProvider.deferIntercept();
+	     *
+	     * }).run(function ($rootScope, $urlRouter, UserService) {
+	     *
+	     *   $rootScope.$on('$locationChangeSuccess', function(e) {
+	     *     // UserService is an example service for managing user state
+	     *     if (UserService.isLoggedIn()) return;
+	     *
+	     *     // Prevent $urlRouter's default handler from firing
+	     *     e.preventDefault();
+	     *
+	     *     UserService.handleLogin().then(function() {
+	     *       // Once the user has logged in, sync the current URL
+	     *       // to the router:
+	     *       $urlRouter.sync();
+	     *     });
+	     *   });
+	     *
+	     *   // Configures $urlRouter's listener *after* your custom listener
+	     *   $urlRouter.listen();
+	     * });
+	     * 
+ * + * @param {boolean} defer Indicates whether to defer location change interception. Passing + * no parameter is equivalent to `true`. + */ + UrlRouterProvider.prototype.deferIntercept = function (defer) { + if (defer === undefined) + defer = true; + this.interceptDeferred = defer; + }; + ; + return UrlRouterProvider; + }()); + exports.UrlRouterProvider = UrlRouterProvider; + var UrlRouter = (function () { + function UrlRouter(urlRouterProvider) { + this.urlRouterProvider = urlRouterProvider; + common_1.bindFunctions(UrlRouter.prototype, this, this); + } + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#sync + * @methodOf ui.router.router.$urlRouter + * + * @description + * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`. + * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event, + * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed + * with the transition by calling `$urlRouter.sync()`. + * + * @example + *
+	     * angular.module('app', ['ui.router'])
+	     *   .run(function($rootScope, $urlRouter) {
+	     *     $rootScope.$on('$locationChangeSuccess', function(evt) {
+	     *       // Halt state change from even starting
+	     *       evt.preventDefault();
+	     *       // Perform custom logic
+	     *       var meetsRequirement = ...
+	     *       // Continue with the update and state transition if logic allows
+	     *       if (meetsRequirement) $urlRouter.sync();
+	     *     });
+	     * });
+	     * 
+ */ + UrlRouter.prototype.sync = function () { + update(this.urlRouterProvider.rules, this.urlRouterProvider.otherwiseFn); + }; + UrlRouter.prototype.listen = function () { + var _this = this; + return this.listener = this.listener || $location.onChange(function (evt) { return update(_this.urlRouterProvider.rules, _this.urlRouterProvider.otherwiseFn, evt); }); + }; + UrlRouter.prototype.update = function (read) { + if (read) { + this.location = $location.url(); + return; + } + if ($location.url() === this.location) + return; + $location.url(this.location); + $location.replace(); + }; + UrlRouter.prototype.push = function (urlMatcher, params, options) { + $location.url(urlMatcher.format(params || {})); + if (options && options.replace) + $location.replace(); + }; + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#href + * @methodOf ui.router.router.$urlRouter + * + * @description + * A URL generation method that returns the compiled URL for a given + * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters. + * + * @example + *
+	     * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
+	     *   person: "bob"
+	     * });
+	     * // $bob == "/about/bob";
+	     * 
+ * + * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate. + * @param {object=} params An object of parameter values to fill the matcher's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher` + */ + UrlRouter.prototype.href = function (urlMatcher, params, options) { + if (!urlMatcher.validates(params)) + return null; + var url = urlMatcher.format(params); + options = options || {}; + var cfg = coreservices_1.services.locationConfig; + var isHtml5 = cfg.html5Mode(); + if (!isHtml5 && url !== null) { + url = "#" + cfg.hashPrefix() + url; + } + url = appendBasePath(url, isHtml5, options.absolute); + if (!options.absolute || !url) { + return url; + } + var slash = (!isHtml5 && url ? '/' : ''), port = cfg.port(); + port = (port === 80 || port === 443 ? '' : ':' + port); + return [cfg.protocol(), '://', cfg.host(), port, slash, url].join(''); + }; + return UrlRouter; + }()); + exports.UrlRouter = UrlRouter; + + +/***/ }, +/* 49 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + /** @module view */ /** for typedoc */ + __export(__webpack_require__(50)); + + +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module view */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var predicates_1 = __webpack_require__(4); + var module_1 = __webpack_require__(2); + var match = function (obj1) { + var keys = []; + for (var _i = 1; _i < arguments.length; _i++) { + keys[_i - 1] = arguments[_i]; + } + return function (obj2) { return keys.reduce(function (memo, key) { return memo && obj1[key] === obj2[key]; }, true); }; + }; + /** + * The View service + */ + var ViewService = (function () { + function ViewService() { + var _this = this; + this.uiViews = []; + this.viewConfigs = []; + this._viewConfigFactories = {}; + this.sync = function () { + var uiViewsByFqn = _this.uiViews.map(function (uiv) { return [uiv.fqn, uiv]; }).reduce(common_1.applyPairs, {}); + /** + * Given a ui-view and a ViewConfig, determines if they "match". + * + * A ui-view has a fully qualified name (fqn) and a context object. The fqn is built from its overall location in + * the DOM, describing its nesting relationship to any parent ui-view tags it is nested inside of. + * + * A ViewConfig has a target ui-view name and a context anchor. The ui-view name can be a simple name, or + * can be a segmented ui-view path, describing a portion of a ui-view fqn. + * + * If the ViewConfig's target ui-view name is a simple name (no dots), then a ui-view matches if: + * - the ui-view's name matches the ViewConfig's target name + * - the ui-view's context matches the ViewConfig's anchor + * + * If the ViewConfig's target ui-view name is a segmented name (with dots), then a ui-view matches if: + * - There exists a parent ui-view where: + * - the parent ui-view's name matches the first segment (index 0) of the ViewConfig's target name + * - the parent ui-view's context matches the ViewConfig's anchor + * - And the remaining segments (index 1..n) of the ViewConfig's target name match the tail of the ui-view's fqn + * + * Example: + * + * DOM: + *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * + * uiViews: [ + * { fqn: "$default", creationContext: { name: "" } }, + * { fqn: "$default.foo", creationContext: { name: "A" } }, + * { fqn: "$default.foo.$default", creationContext: { name: "A.B" } } + * { fqn: "$default.foo.$default.bar", creationContext: { name: "A.B.C" } } + * ] + * + * These four view configs all match the ui-view with the fqn: "$default.foo.$default.bar": + * + * - ViewConfig1: { uiViewName: "bar", uiViewContextAnchor: "A.B.C" } + * - ViewConfig2: { uiViewName: "$default.bar", uiViewContextAnchor: "A.B" } + * - ViewConfig3: { uiViewName: "foo.$default.bar", uiViewContextAnchor: "A" } + * - ViewConfig4: { uiViewName: "$default.foo.$default.bar", uiViewContextAnchor: "" } + * + * Using ViewConfig3 as an example, it matches the ui-view with fqn "$default.foo.$default.bar" because: + * - The ViewConfig's segmented target name is: [ "foo", "$default", "bar" ] + * - There exists a parent ui-view (which has fqn: "$default.foo") where: + * - the parent ui-view's name "foo" matches the first segment "foo" of the ViewConfig's target name + * - the parent ui-view's context "A" matches the ViewConfig's anchor context "A" + * - And the remaining segments [ "$default", "bar" ].join("."_ of the ViewConfig's target name match + * the tail of the ui-view's fqn "default.bar" + */ + var matches = function (uiView) { return function (viewConfig) { + // Split names apart from both viewConfig and uiView into segments + var vc = viewConfig.viewDecl; + var vcSegments = vc.$uiViewName.split("."); + var uivSegments = uiView.fqn.split("."); + // Check if the tails of the segment arrays match. ex, these arrays' tails match: + // vc: ["foo", "bar"], uiv fqn: ["$default", "foo", "bar"] + if (!common_1.equals(vcSegments, uivSegments.slice(0 - vcSegments.length))) + return false; + // Now check if the fqn ending at the first segment of the viewConfig matches the context: + // ["$default", "foo"].join(".") == "$default.foo", does the ui-view $default.foo context match? + var negOffset = (1 - vcSegments.length) || undefined; + var fqnToFirstSegment = uivSegments.slice(0, negOffset).join("."); + var uiViewContext = uiViewsByFqn[fqnToFirstSegment].creationContext; + return vc.$uiViewContextAnchor === (uiViewContext && uiViewContext.name); + }; }; + // Return the number of dots in the fully qualified name + function uiViewDepth(uiView) { + return uiView.fqn.split(".").length; + } + // Return the ViewConfig's context's depth in the context tree. + function viewConfigDepth(config) { + var context = config.viewDecl.$context, count = 0; + while (++count && context.parent) + context = context.parent; + return count; + } + // Given a depth function, returns a compare function which can return either ascending or descending order + var depthCompare = hof_1.curry(function (depthFn, posNeg, left, right) { return posNeg * (depthFn(left) - depthFn(right)); }); + var matchingConfigPair = function (uiView) { + var matchingConfigs = _this.viewConfigs.filter(matches(uiView)); + if (matchingConfigs.length > 1) + matchingConfigs.sort(depthCompare(viewConfigDepth, -1)); // descending + return [uiView, matchingConfigs[0]]; + }; + var configureUiView = function (_a) { + var uiView = _a[0], viewConfig = _a[1]; + // If a parent ui-view is reconfigured, it could destroy child ui-views. + // Before configuring a child ui-view, make sure it's still in the active uiViews array. + if (_this.uiViews.indexOf(uiView) !== -1) + uiView.configUpdated(viewConfig); + }; + _this.uiViews.sort(depthCompare(uiViewDepth, 1)).map(matchingConfigPair).forEach(configureUiView); + }; + } + ViewService.prototype.rootContext = function (context) { + return this._rootContext = context || this._rootContext; + }; + ; + ViewService.prototype.viewConfigFactory = function (viewType, factory) { + this._viewConfigFactories[viewType] = factory; + }; + ViewService.prototype.createViewConfig = function (node, decl) { + var cfgFactory = this._viewConfigFactories[decl.$type]; + if (!cfgFactory) + throw new Error("ViewService: No view config factory registered for type " + decl.$type); + return cfgFactory(node, decl); + }; + /** + * De-registers a ViewConfig. + * + * @param viewConfig The ViewConfig view to deregister. + */ + ViewService.prototype.deactivateViewConfig = function (viewConfig) { + module_1.trace.traceViewServiceEvent("<- Removing", viewConfig); + common_1.removeFrom(this.viewConfigs, viewConfig); + }; + ; + ViewService.prototype.activateViewConfig = function (viewConfig) { + module_1.trace.traceViewServiceEvent("-> Registering", viewConfig); + this.viewConfigs.push(viewConfig); + }; + ; + /** + * Allows a `ui-view` element to register its canonical name with a callback that allows it to + * be updated with a template, controller, and local variables. + * + * @param {String} name The fully-qualified name of the `ui-view` object being registered. + * @param {Function} configUpdatedCallback A callback that receives updates to the content & configuration + * of the view. + * @return {Function} Returns a de-registration function used when the view is destroyed. + */ + ViewService.prototype.registerUiView = function (uiView) { + module_1.trace.traceViewServiceUiViewEvent("-> Registering", uiView); + var uiViews = this.uiViews; + var fqnMatches = function (uiv) { return uiv.fqn === uiView.fqn; }; + if (uiViews.filter(fqnMatches).length) + module_1.trace.traceViewServiceUiViewEvent("!!!! duplicate uiView named:", uiView); + uiViews.push(uiView); + this.sync(); + return function () { + var idx = uiViews.indexOf(uiView); + if (idx <= 0) { + module_1.trace.traceViewServiceUiViewEvent("Tried removing non-registered uiView", uiView); + return; + } + module_1.trace.traceViewServiceUiViewEvent("<- Deregistering", uiView); + common_1.removeFrom(uiViews)(uiView); + }; + }; + ; + /** + * Returns the list of views currently available on the page, by fully-qualified name. + * + * @return {Array} Returns an array of fully-qualified view names. + */ + ViewService.prototype.available = function () { + return this.uiViews.map(hof_1.prop("fqn")); + }; + /** + * Returns the list of views on the page containing loaded content. + * + * @return {Array} Returns an array of fully-qualified view names. + */ + ViewService.prototype.active = function () { + return this.uiViews.filter(hof_1.prop("$config")).map(hof_1.prop("name")); + }; + /** + * Normalizes a view's name from a state.views configuration block. + * + * @param context the context object (state declaration) that the view belongs to + * @param rawViewName the name of the view, as declared in the [[StateDeclaration.views]] + * + * @returns the normalized uiViewName and uiViewContextAnchor that the view targets + */ + ViewService.normalizeUiViewTarget = function (context, rawViewName) { + if (rawViewName === void 0) { rawViewName = ""; } + // TODO: Validate incoming view name with a regexp to allow: + // ex: "view.name@foo.bar" , "^.^.view.name" , "view.name@^.^" , "" , + // "@" , "$default@^" , "!$default.$default" , "!foo.bar" + var viewAtContext = rawViewName.split("@"); + var uiViewName = viewAtContext[0] || "$default"; // default to unnamed view + var uiViewContextAnchor = predicates_1.isString(viewAtContext[1]) ? viewAtContext[1] : "^"; // default to parent context + // Handle relative view-name sugar syntax. + // Matches rawViewName "^.^.^.foo.bar" into array: ["^.^.^.foo.bar", "^.^.^", "foo.bar"], + var relativeViewNameSugar = /^(\^(?:\.\^)*)\.(.*$)/.exec(uiViewName); + if (relativeViewNameSugar) { + // Clobbers existing contextAnchor (rawViewName validation will fix this) + uiViewContextAnchor = relativeViewNameSugar[1]; // set anchor to "^.^.^" + uiViewName = relativeViewNameSugar[2]; // set view-name to "foo.bar" + } + if (uiViewName.charAt(0) === '!') { + uiViewName = uiViewName.substr(1); + uiViewContextAnchor = ""; // target absolutely from root + } + // handle parent relative targeting "^.^.^" + var relativeMatch = /^(\^(?:\.\^)*)$/; + if (relativeMatch.exec(uiViewContextAnchor)) { + var anchor = uiViewContextAnchor.split(".").reduce((function (anchor, x) { return anchor.parent; }), context); + uiViewContextAnchor = anchor.name; + } + return { uiViewName: uiViewName, uiViewContextAnchor: uiViewContextAnchor }; + }; + return ViewService; + }()); + exports.ViewService = ViewService; + + +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module core */ /** */ + var stateParams_1 = __webpack_require__(25); + var queue_1 = __webpack_require__(8); + var common_1 = __webpack_require__(3); + /** + * Global mutable state + * + * This is where we hold the global mutable state such as current state, current + * params, current transition, last successful transition, last attempted transition, etc. + */ + var UIRouterGlobals = (function () { + function UIRouterGlobals(transitionService) { + var _this = this; + /** + * Current parameter values + * + * The parameter values from the latest successful transition + */ + this.params = new stateParams_1.StateParams(); + /** + * The transition history + * + * This queue's size is limited to a maximum number (default: 1) + */ + this.transitionHistory = new queue_1.Queue([], 1); + /** + * The history of successful transitions + * + * This queue's size is limited to a maximum number (default: 1) + */ + this.successfulTransitions = new queue_1.Queue([], 1); + var beforeNewTransition = function ($transition$) { + _this.transition = $transition$; + _this.transitionHistory.enqueue($transition$); + var updateGlobalState = function () { + _this.successfulTransitions.enqueue($transition$); + _this.$current = $transition$.$to(); + _this.current = _this.$current.self; + common_1.copy($transition$.params(), _this.params); + }; + $transition$.onSuccess({}, updateGlobalState, { priority: 10000 }); + var clearCurrentTransition = function () { if (_this.transition === $transition$) + _this.transition = null; }; + $transition$.promise.then(clearCurrentTransition, clearCurrentTransition); + }; + transitionService.onBefore({}, ['$transition$', beforeNewTransition]); + } + return UIRouterGlobals; + }()); + exports.UIRouterGlobals = UIRouterGlobals; + + +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module core */ /** */ + var urlMatcherFactory_1 = __webpack_require__(47); + var urlRouter_1 = __webpack_require__(48); + var state_1 = __webpack_require__(18); + var urlRouter_2 = __webpack_require__(48); + var transitionService_1 = __webpack_require__(43); + var view_1 = __webpack_require__(50); + var stateRegistry_1 = __webpack_require__(36); + var stateService_1 = __webpack_require__(37); + var globals_1 = __webpack_require__(51); + /** + * The master class used to instantiate an instance of UI-Router. + * + * This class instantiates and wires the global UI-Router services. + * + * After instantiating a new instance of the Router class, configure it for your app. For instance, register + * your app states with the [[stateRegistry]] (and set url options using ...). Then, tell UI-Router to monitor + * the URL by calling `urlRouter.listen()` ([[URLRouter.listen]]) + */ + var UIRouter = (function () { + function UIRouter() { + this.viewService = new view_1.ViewService(); + this.transitionService = new transitionService_1.TransitionService(this.viewService); + this.globals = new globals_1.UIRouterGlobals(this.transitionService); + this.urlMatcherFactory = new urlMatcherFactory_1.UrlMatcherFactory(); + this.urlRouterProvider = new urlRouter_1.UrlRouterProvider(this.urlMatcherFactory, this.globals.params); + this.urlRouter = new urlRouter_2.UrlRouter(this.urlRouterProvider); + this.stateRegistry = new stateRegistry_1.StateRegistry(this.urlMatcherFactory, this.urlRouterProvider); + /** @hidden TODO: move this to ng1.ts */ + this.stateProvider = new state_1.StateProvider(this.stateRegistry); + this.stateService = new stateService_1.StateService(this.viewService, this.urlRouter, this.transitionService, this.stateRegistry, this.stateProvider, this.globals); + this.viewService.rootContext(this.stateRegistry.root()); + this.globals.$current = this.stateRegistry.root(); + this.globals.current = this.globals.$current.self; + } + return UIRouter; + }()); + exports.UIRouter = UIRouter; + + +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * # UI-Router for Angular 1 + * + * - Provides an implementation for the [[CoreServices]] API, based on angular 1 services. + * - Also registers some services with the angular 1 injector. + * - Creates and bootstraps a new [[UIRouter]] object. Ties it to the the angular 1 lifecycle. + * + * @module ng1 + * @preferred + */ + "use strict"; + /** for typedoc */ + var router_1 = __webpack_require__(52); + var coreservices_1 = __webpack_require__(6); + var common_1 = __webpack_require__(3); + var hof_1 = __webpack_require__(5); + var predicates_1 = __webpack_require__(4); + var module_1 = __webpack_require__(44); + var module_2 = __webpack_require__(40); + var module_3 = __webpack_require__(17); + var trace_1 = __webpack_require__(12); + var viewsBuilder_1 = __webpack_require__(54); + var templateFactory_1 = __webpack_require__(55); + /** @hidden */ + var app = angular.module("ui.router.angular1", []); + /** + * @ngdoc overview + * @name ui.router.util + * + * @description + * # ui.router.util sub-module + * + * This module is a dependency of other sub-modules. Do not include this module as a dependency + * in your angular app (use {@link ui.router} module instead). + * + */ + angular.module('ui.router.util', ['ng', 'ui.router.init']); + /** + * @ngdoc overview + * @name ui.router.router + * + * @requires ui.router.util + * + * @description + * # ui.router.router sub-module + * + * This module is a dependency of other sub-modules. Do not include this module as a dependency + * in your angular app (use {@link ui.router} module instead). + */ + angular.module('ui.router.router', ['ui.router.util']); + /** + * @ngdoc overview + * @name ui.router.state + * + * @requires ui.router.router + * @requires ui.router.util + * + * @description + * # ui.router.state sub-module + * + * This module is a dependency of the main ui.router module. Do not include this module as a dependency + * in your angular app (use {@link ui.router} module instead). + * + */ + angular.module('ui.router.state', ['ui.router.router', 'ui.router.util', 'ui.router.angular1']); + /** + * @ngdoc overview + * @name ui.router + * + * @requires ui.router.state + * + * @description + * # ui.router + * + * ## The main module for ui.router + * There are several sub-modules included with the ui.router module, however only this module is needed + * as a dependency within your angular app. The other modules are for organization purposes. + * + * The modules are: + * * ui.router - the main "umbrella" module + * * ui.router.router - + * + * *You'll need to include **only** this module as the dependency within your angular app.* + * + *
+	 * 
+	 * 
+	 * 
+	 *   
+	 *   
+	 *   
+	 *   
+	 * 
+	 * 
+	 * 
+	 * 
+	 * 
+ */ + angular.module('ui.router', ['ui.router.init', 'ui.router.state', 'ui.router.angular1']); + angular.module('ui.router.compat', ['ui.router']); + /** + * Annotates a controller expression (may be a controller function(), a "controllername", + * or "controllername as name") + * + * - Temporarily decorates $injector.instantiate. + * - Invokes $controller() service + * - Calls $injector.instantiate with controller constructor + * - Annotate constructor + * - Undecorate $injector + * + * returns an array of strings, which are the arguments of the controller expression + */ + function annotateController(controllerExpression) { + var $injector = coreservices_1.services.$injector; + var $controller = $injector.get("$controller"); + var oldInstantiate = $injector.instantiate; + try { + var deps_1; + $injector.instantiate = function fakeInstantiate(constructorFunction) { + $injector.instantiate = oldInstantiate; // Un-decorate ASAP + deps_1 = $injector.annotate(constructorFunction); + }; + $controller(controllerExpression, { $scope: {} }); + return deps_1; + } + finally { + $injector.instantiate = oldInstantiate; + } + } + exports.annotateController = annotateController; + runBlock.$inject = ['$injector', '$q']; + function runBlock($injector, $q) { + coreservices_1.services.$injector = $injector; + coreservices_1.services.$q = $q; + } + app.run(runBlock); + var router = null; + ng1UIRouter.$inject = ['$locationProvider']; + /** This angular 1 provider instantiates a Router and exposes its services via the angular injector */ + function ng1UIRouter($locationProvider) { + // Create a new instance of the Router when the ng1UIRouterProvider is initialized + router = new router_1.UIRouter(); + // Apply ng1 `views` builder to the StateBuilder + router.stateRegistry.decorator("views", viewsBuilder_1.ng1ViewsBuilder); + router.viewService.viewConfigFactory('ng1', viewsBuilder_1.ng1ViewConfigFactory); + // Bind LocationConfig.hashPrefix to $locationProvider.hashPrefix + common_1.bindFunctions($locationProvider, coreservices_1.services.locationConfig, $locationProvider, ['hashPrefix']); + // Create a LocationService.onChange registry + var urlListeners = []; + coreservices_1.services.location.onChange = function (callback) { + urlListeners.push(callback); + return function () { return common_1.removeFrom(urlListeners)(callback); }; + }; + this.$get = $get; + $get.$inject = ['$location', '$browser', '$sniffer', '$rootScope', '$http', '$templateCache']; + function $get($location, $browser, $sniffer, $rootScope, $http, $templateCache) { + // Bind $locationChangeSuccess to the listeners registered in LocationService.onChange + $rootScope.$on("$locationChangeSuccess", function (evt) { return urlListeners.forEach(function (fn) { return fn(evt); }); }); + // Bind LocationConfig.html5Mode to $locationProvider.html5Mode and $sniffer.history + coreservices_1.services.locationConfig.html5Mode = function () { + var html5Mode = $locationProvider.html5Mode(); + html5Mode = predicates_1.isObject(html5Mode) ? html5Mode.enabled : html5Mode; + return html5Mode && $sniffer.history; + }; + coreservices_1.services.template.get = function (url) { + return $http.get(url, { cache: $templateCache, headers: { Accept: 'text/html' } }).then(hof_1.prop("data")); + }; + // Bind these LocationService functions to $location + common_1.bindFunctions($location, coreservices_1.services.location, $location, ["replace", "url", "path", "search", "hash"]); + // Bind these LocationConfig functions to $location + common_1.bindFunctions($location, coreservices_1.services.locationConfig, $location, ['port', 'protocol', 'host']); + // Bind these LocationConfig functions to $browser + common_1.bindFunctions($browser, coreservices_1.services.locationConfig, $browser, ['baseHref']); + return router; + } + } + var resolveFactory = function () { return ({ + /** + * This emulates most of the behavior of the ui-router 0.2.x $resolve.resolve() service API. + * @param invocables an object, with keys as resolve names and values as injectable functions + * @param locals key/value pre-resolved data (locals) + * @param parent a promise for a "parent resolve" + */ + resolve: function (invocables, locals, parent) { + if (locals === void 0) { locals = {}; } + var parentNode = new module_1.Node(new module_3.State({ params: {} })); + var node = new module_1.Node(new module_3.State({ params: {} })); + var context = new module_2.ResolveContext([parentNode, node]); + context.addResolvables(module_2.Resolvable.makeResolvables(invocables), node.state); + var resolveData = function (parentLocals) { + var rewrap = function (_locals) { return module_2.Resolvable.makeResolvables(common_1.map(_locals, function (local) { return function () { return local; }; })); }; + context.addResolvables(rewrap(parentLocals), parentNode.state); + context.addResolvables(rewrap(locals), node.state); + return context.resolvePath(); + }; + return parent ? parent.then(resolveData) : resolveData({}); + } + }); }; + function $stateParamsFactory(ng1UIRouter) { + return ng1UIRouter.globals.params; + } + // The 'ui.router' ng1 module depends on 'ui.router.init' module. + angular.module('ui.router.init', []).provider("ng1UIRouter", ng1UIRouter); + // This effectively calls $get() to init when we enter runtime + angular.module('ui.router.init').run(['ng1UIRouter', function (ng1UIRouter) { }]); + // $urlMatcherFactory service and $urlMatcherFactoryProvider + angular.module('ui.router.util').provider('$urlMatcherFactory', ['ng1UIRouterProvider', function () { return router.urlMatcherFactory; }]); + angular.module('ui.router.util').run(['$urlMatcherFactory', function ($urlMatcherFactory) { }]); + // $urlRouter service and $urlRouterProvider + function getUrlRouterProvider() { + router.urlRouterProvider["$get"] = function () { + router.urlRouter.update(true); + if (!this.interceptDeferred) + router.urlRouter.listen(); + return router.urlRouter; + }; + return router.urlRouterProvider; + } + angular.module('ui.router.router').provider('$urlRouter', ['ng1UIRouterProvider', getUrlRouterProvider]); + angular.module('ui.router.router').run(['$urlRouter', function ($urlRouter) { }]); + // $state service and $stateProvider + // $urlRouter service and $urlRouterProvider + function getStateProvider() { + router.stateProvider["$get"] = function () { + // Autoflush once we are in runtime + router.stateRegistry.stateQueue.autoFlush(router.stateService); + return router.stateService; + }; + return router.stateProvider; + } + angular.module('ui.router.state').provider('$state', ['ng1UIRouterProvider', getStateProvider]); + angular.module('ui.router.state').run(['$state', function ($state) { }]); + // $stateParams service + angular.module('ui.router.state').factory('$stateParams', ['ng1UIRouter', function (ng1UIRouter) { + return ng1UIRouter.globals.params; + }]); + // $transitions service and $transitionsProvider + function getTransitionsProvider() { + loadAllControllerLocals.$inject = ['$transition$']; + function loadAllControllerLocals($transition$) { + var loadLocals = function (vc) { + var node = common_1.find($transition$.treeChanges().to, hof_1.propEq('state', vc.viewDecl.$context)); + // Temporary fix; This whole callback should be nuked when fixing #2662 + if (!node) + return coreservices_1.services.$q.when(); + var resolveCtx = node.resolveContext; + var controllerDeps = annotateController(vc.controller); + var resolvables = resolveCtx.getResolvables(); + function $loadControllerLocals() { } + $loadControllerLocals.$inject = controllerDeps.filter(function (dep) { return resolvables.hasOwnProperty(dep); }); + // Load any controller resolves that aren't already loaded + return resolveCtx.invokeLater($loadControllerLocals) + .then(function () { return vc.locals = common_1.map(resolvables, function (res) { return res.data; }); }); + }; + var loadAllLocals = $transition$.views("entering").filter(function (vc) { return !!vc.controller; }).map(loadLocals); + return coreservices_1.services.$q.all(loadAllLocals).then(common_1.noop); + } + router.transitionService.onFinish({}, loadAllControllerLocals); + router.transitionService["$get"] = function () { return router.transitionService; }; + return router.transitionService; + } + angular.module('ui.router.state').provider('$transitions', ['ng1UIRouterProvider', getTransitionsProvider]); + // $templateFactory service + angular.module('ui.router.util').factory('$templateFactory', ['ng1UIRouter', function () { return new templateFactory_1.TemplateFactory(); }]); + // The $view service + angular.module('ui.router').factory('$view', function () { return router.viewService; }); + // The old $resolve service + angular.module('ui.router').factory('$resolve', resolveFactory); + // $trace service + angular.module("ui.router").service("$trace", function () { return trace_1.trace; }); + watchDigests.$inject = ['$rootScope']; + function watchDigests($rootScope) { + $rootScope.$watch(function () { trace_1.trace.approximateDigests++; }); + } + exports.watchDigests = watchDigests; + angular.module("ui.router").run(watchDigests); + + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + var common_1 = __webpack_require__(3); + var strings_1 = __webpack_require__(9); + var view_1 = __webpack_require__(50); + var predicates_1 = __webpack_require__(4); + var coreservices_1 = __webpack_require__(6); + var trace_1 = __webpack_require__(12); + var templateFactory_1 = __webpack_require__(55); + exports.ng1ViewConfigFactory = function (node, view) { return new Ng1ViewConfig(node, view); }; + /** + * This is a [[StateBuilder.builder]] function for angular1 `views`. + * + * When the [[StateBuilder]] builds a [[State]] object from a raw [[StateDeclaration]], this builder + * handles the `views` property with logic specific to angular-ui-router (ng1). + * + * If no `views: {}` property exists on the [[StateDeclaration]], then it creates the `views` object + * and applies the state-level configuration to a view named `$default`. + */ + function ng1ViewsBuilder(state) { + var tplKeys = ['templateProvider', 'templateUrl', 'template', 'notify', 'async'], ctrlKeys = ['controller', 'controllerProvider', 'controllerAs', 'resolveAs'], compKeys = ['component', 'bindings'], nonCompKeys = tplKeys.concat(ctrlKeys), allKeys = compKeys.concat(nonCompKeys); + var views = {}, viewsObject = state.views || { "$default": common_1.pick(state, allKeys) }; + common_1.forEach(viewsObject, function (config, name) { + // Account for views: { "": { template... } } + name = name || "$default"; + // Account for views: { header: "headerComponent" } + if (predicates_1.isString(config)) + config = { component: config }; + if (!Object.keys(config).length) + return; + // Configure this view for routing to an angular 1.5+ style .component (or any directive, really) + if (config.component) { + if (nonCompKeys.map(function (key) { return predicates_1.isDefined(config[key]); }).reduce(common_1.anyTrueR, false)) { + throw new Error("Cannot combine: " + compKeys.join("|") + " with: " + nonCompKeys.join("|") + " in stateview: 'name@" + state.name + "'"); + } + // Dynamically build a template like "" + config.templateProvider = ['$injector', function ($injector) { + var resolveFor = function (key) { return config.bindings && config.bindings[key] || key; }; + var prefix = angular.version.minor >= 3 ? "::" : ""; + var attrs = getComponentInputs($injector, config.component) + .map(function (key) { return (strings_1.kebobString(key) + "='" + prefix + "$resolve." + resolveFor(key) + "'"); }).join(" "); + var kebobName = strings_1.kebobString(config.component); + return "<" + kebobName + " " + attrs + ">"; + }]; + } + config.resolveAs = config.resolveAs || '$resolve'; + config.$type = "ng1"; + config.$context = state; + config.$name = name; + var normalized = view_1.ViewService.normalizeUiViewTarget(config.$context, config.$name); + config.$uiViewName = normalized.uiViewName; + config.$uiViewContextAnchor = normalized.uiViewContextAnchor; + views[name] = config; + }); + return views; + } + exports.ng1ViewsBuilder = ng1ViewsBuilder; + // for ng 1.2 style, process the scope: { input: "=foo" } object + var scopeBindings = function (bindingsObj) { return Object.keys(bindingsObj || {}) + .map(function (key) { return [key, /^[=<](.*)/.exec(bindingsObj[key])]; }) + .filter(function (tuple) { return predicates_1.isDefined(tuple[1]); }) + .map(function (tuple) { return tuple[1][1] || tuple[0]; }); }; + // for ng 1.3+ bindToController or 1.5 component style, process a $$bindings object + var bindToCtrlBindings = function (bindingsObj) { return Object.keys(bindingsObj || {}) + .filter(function (key) { return !!/[=<]/.exec(bindingsObj[key].mode); }) + .map(function (key) { return bindingsObj[key].attrName; }); }; + // Given a directive definition, find its object input attributes + // Use different properties, depending on the type of directive (component, bindToController, normal) + var getBindings = function (def) { + if (predicates_1.isObject(def.bindToController)) + return scopeBindings(def.bindToController); + if (def.$$bindings && def.$$bindings.bindToController) + return bindToCtrlBindings(def.$$bindings.bindToController); + if (def.$$isolateBindings) + return bindToCtrlBindings(def.$$isolateBindings); + return scopeBindings(def.scope); + }; + // Gets all the directive(s)' inputs ('=' and '<') + function getComponentInputs($injector, name) { + var cmpDefs = $injector.get(name + "Directive"); // could be multiple + if (!cmpDefs || !cmpDefs.length) + throw new Error("Unable to find component named '" + name + "'"); + return cmpDefs.map(getBindings).reduce(common_1.unnestR, []); + } + var Ng1ViewConfig = (function () { + function Ng1ViewConfig(node, viewDecl) { + this.node = node; + this.viewDecl = viewDecl; + this.loaded = false; + } + Ng1ViewConfig.prototype.load = function () { + var _this = this; + var $q = coreservices_1.services.$q; + if (!this.hasTemplate()) + throw new Error("No template configuration specified for '" + this.viewDecl.$uiViewName + "@" + this.viewDecl.$uiViewContextAnchor + "'"); + var injector = this.node.resolveContext; + var params = this.node.paramValues; + var promises = { + template: $q.when(this.getTemplate(params, new templateFactory_1.TemplateFactory(), injector)), + controller: $q.when(this.getController(injector)) + }; + return $q.all(promises).then(function (results) { + trace_1.trace.traceViewServiceEvent("Loaded", _this); + _this.controller = results.controller; + _this.template = results.template; + }); + }; + /** + * Checks a view configuration to ensure that it specifies a template. + * + * @return {boolean} Returns `true` if the configuration contains a valid template, otherwise `false`. + */ + Ng1ViewConfig.prototype.hasTemplate = function () { + return !!(this.viewDecl.template || this.viewDecl.templateUrl || this.viewDecl.templateProvider); + }; + Ng1ViewConfig.prototype.getTemplate = function (params, $factory, injector) { + return $factory.fromConfig(this.viewDecl, params, injector.invokeLater.bind(injector)); + }; + /** + * Gets the controller for a view configuration. + * + * @returns {Function|Promise.} Returns a controller, or a promise that resolves to a controller. + */ + Ng1ViewConfig.prototype.getController = function (injector) { + //* @param {Object} locals A context object from transition.context() to invoke a function in the correct context + var provider = this.viewDecl.controllerProvider; + return predicates_1.isInjectable(provider) ? injector.invokeLater(provider, {}) : this.viewDecl.controller; + }; + return Ng1ViewConfig; + }()); + exports.Ng1ViewConfig = Ng1ViewConfig; + + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** @module view */ /** for typedoc */ + var predicates_1 = __webpack_require__(4); + var coreservices_1 = __webpack_require__(6); + /** + * Service which manages loading of templates from a ViewConfig. + */ + var TemplateFactory = (function () { + function TemplateFactory() { + } + /** + * Creates a template from a configuration object. + * + * @param 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 params Parameters to pass to the template function. + * @param injectFn Function to which an injectable function may be passed. + * If templateProvider is defined, this injectFn will be used to invoke it. + * + * @return {string|object} The template html as a string, or a promise for + * that string,or `null` if no template is configured. + */ + TemplateFactory.prototype.fromConfig = function (config, params, injectFn) { + return (predicates_1.isDefined(config.template) ? this.fromString(config.template, params) : + predicates_1.isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) : + predicates_1.isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, injectFn) : + null); + }; + ; + /** + * Creates a template from a string or a function returning a string. + * + * @param template html template as a string or function that returns an html template as a string. + * @param params Parameters to pass to the template function. + * + * @return {string|object} The template html as a string, or a promise for that + * string. + */ + TemplateFactory.prototype.fromString = function (template, params) { + return predicates_1.isFunction(template) ? template(params) : template; + }; + ; + /** + * Loads a template from the a URL via `$http` and `$templateCache`. + * + * @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.} The template html as a string, or a promise + * for that string. + */ + TemplateFactory.prototype.fromUrl = function (url, params) { + if (predicates_1.isFunction(url)) + url = url(params); + if (url == null) + return null; + return coreservices_1.services.template.get(url); + }; + ; + /** + * Creates a template by invoking an injectable provider function. + * + * @param provider Function to invoke via `locals` + * @param {Function} injectFn a function used to invoke the template provider + * @return {string|Promise.} The template html as a string, or a promise + * for that string. + */ + TemplateFactory.prototype.fromProvider = function (provider, params, injectFn) { + return injectFn(provider); + }; + ; + return TemplateFactory; + }()); + exports.TemplateFactory = TemplateFactory; + + +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + /** + * These are the UI-Router angular 1 directives. + * + * These directives are used in templates to create viewports and navigate to states + * + * @preferred @module ng1_directives + */ /** for typedoc */ + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var hof_1 = __webpack_require__(5); + /** @hidden */ + function parseStateRef(ref, current) { + var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed; + if (preparsed) + ref = current + '(' + preparsed[1] + ')'; + parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); + if (!parsed || parsed.length !== 4) + throw new Error("Invalid state ref '" + ref + "'"); + return { state: parsed[1], paramExpr: parsed[3] || null }; + } + /** @hidden */ + function stateContext(el) { + var $uiView = el.parent().inheritedData('$uiView'); + var context = hof_1.parse('$cfg.node.state')($uiView); + return context && context.name ? context : undefined; + } + /** @hidden */ + function getTypeInfo(el) { + // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. + var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]'; + var isForm = el[0].nodeName === "FORM"; + return { + attr: isForm ? "action" : (isSvg ? 'xlink:href' : 'href'), + isAnchor: el.prop("tagName").toUpperCase() === "A", + clickable: !isForm + }; + } + /** @hidden */ + function clickHook(el, $state, $timeout, type, current) { + return function (e) { + var button = e.which || e.button, target = current(); + if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) { + // HACK: This is to allow ng-clicks to be processed before the transition is initiated: + var transition = $timeout(function () { + $state.go(target.state, target.params, target.options); + }); + e.preventDefault(); + // if the state has no URL, ignore one preventDefault from the directive. + var ignorePreventDefaultCount = type.isAnchor && !target.href ? 1 : 0; + e.preventDefault = function () { + if (ignorePreventDefaultCount-- <= 0) + $timeout.cancel(transition); + }; + } + }; + } + /** @hidden */ + function defaultOpts(el, $state) { + return { relative: stateContext(el) || $state.$current, inherit: true }; + } + /** + * `ui-sref`: A directive for linking to a state + * + * A directive that binds a link (`` tag) to a state. If the state has an associated + * URL, the directive will automatically generate & update the `href` attribute via + * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking + * the link will trigger a state transition with optional parameters. + * + * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be + * handled natively by the browser. + * + * You can also use relative state paths within ui-sref, just like the relative + * paths passed to `$state.go()`. You just need to be aware that the path is relative + * to the state that the link lives in, in other words the state that loaded the + * template containing the link. + * + * You can specify options to pass to {@link ui.router.state.$state#go $state.go()} + * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`, + * and `reload`. + * + * Here's an example of how you'd use ui-sref and how it would compile. If you have the + * following template: + * + * @example + * ```html + * + *
+	 * Home | About | Next page
+	 *
+	 * 
+	 * 
+ * ``` + * + * Then the compiled html would be (assuming Html5Mode is off and current state is contacts): + * + * ```html + * + *
+	 * Home | About | Next page
+	 *
+	 * 
    + *
  • + * Joe + *
  • + *
  • + * Alice + *
  • + *
  • + * Bob + *
  • + *
+ * + * Home + *
+ * ``` + * + * @param {string} ui-sref 'stateName' can be any valid absolute or relative state + * @param {Object} ui-sref-opts options to pass to [[StateService.go]] + */ + var uiSrefNg1 = ['$state', '$timeout', + function $StateRefDirective($state, $timeout) { + return { + restrict: 'A', + require: ['?^uiSrefActive', '?^uiSrefActiveEq'], + link: function (scope, element, attrs, uiSrefActive) { + var ref = parseStateRef(attrs.uiSref, $state.current.name); + var def = { state: ref.state, href: null, params: null, options: null }; + var type = getTypeInfo(element); + var active = uiSrefActive[1] || uiSrefActive[0]; + var unlinkInfoFn = null; + def.options = common_1.extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {}); + var update = function (val) { + if (val) + def.params = angular.copy(val); + def.href = $state.href(ref.state, def.params, def.options); + if (unlinkInfoFn) + unlinkInfoFn(); + if (active) + unlinkInfoFn = active.$$addStateInfo(ref.state, def.params); + if (def.href !== null) + attrs.$set(type.attr, def.href); + }; + if (ref.paramExpr) { + scope.$watch(ref.paramExpr, function (val) { if (val !== def.params) + update(val); }, true); + def.params = angular.copy(scope.$eval(ref.paramExpr)); + } + update(); + if (!type.clickable) + return; + element.bind("click", clickHook(element, $state, $timeout, type, function () { return def; })); + } + }; + }]; + /** + * `ui-state`: A dynamic version of `ui-sref` + * + * Much like ui-sref, but will accept named $scope properties to evaluate for a state definition, + * params and override options. + * + * @example + * ```html + * + *
  • + * {{nav.description}} + *
  • + * + * @param {string} ui-state 'stateName' can be any valid absolute or relative state + * @param {Object} ui-state-params params to pass to [[StateService.href]] + * @param {Object} ui-state-opts options to pass to [[StateService.go]] + */ + var uiStateNg1 = ['$state', '$timeout', + function $StateRefDynamicDirective($state, $timeout) { + return { + restrict: 'A', + require: ['?^uiSrefActive', '?^uiSrefActiveEq'], + link: function (scope, element, attrs, uiSrefActive) { + var type = getTypeInfo(element); + var active = uiSrefActive[1] || uiSrefActive[0]; + var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null]; + var watch = '[' + group.map(function (val) { return val || 'null'; }).join(', ') + ']'; + var def = { state: null, params: null, options: null, href: null }; + var unlinkInfoFn = null; + function runStateRefLink(group) { + def.state = group[0]; + def.params = group[1]; + def.options = group[2]; + def.href = $state.href(def.state, def.params, def.options); + if (unlinkInfoFn) + unlinkInfoFn(); + if (active) + unlinkInfoFn = active.$$addStateInfo(def.state, def.params); + if (def.href) + attrs.$set(type.attr, def.href); + } + scope.$watch(watch, runStateRefLink, true); + runStateRefLink(scope.$eval(watch)); + if (!type.clickable) + return; + element.bind("click", clickHook(element, $state, $timeout, type, function () { return def; })); + } + }; + }]; + /** + * `ui-sref-active` and `ui-sref-active-eq`: A directive that adds a CSS class when a `ui-sref` is active + * + * A directive working alongside ui-sref to add classes to an element when the + * related ui-sref directive's state is active, and removing them when it is inactive. + * The primary use-case is to simplify the special appearance of navigation menus + * relying on `ui-sref`, by having the "active" state's menu button appear different, + * distinguishing it from the inactive menu items. + * + * ui-sref-active can live on the same element as ui-sref or on a parent element. The first + * ui-sref-active found at the same level or above the ui-sref will be used. + * + * Will activate when the ui-sref's target state or any child state is active. If you + * need to activate only when the ui-sref target state is active and *not* any of + * it's children, then you will use ui-sref-active-eq + * + * Given the following template: + * @example + * ```html + * + *
    +	 * 
    +	 * 
    + * ``` + * + * + * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins", + * the resulting HTML will appear as (note the 'active' class): + * + * ```html + * + *
    +	 * 
    +	 * 
    + * ``` + * + * The class name is interpolated **once** during the directives link time (any further changes to the + * interpolated value are ignored). + * + * Multiple classes may be specified in a space-separated format: + * + * ```html + *
    +	 * 
      + *
    • + * link + *
    • + *
    + *
    + * ``` + * + * It is also possible to pass ui-sref-active an expression that evaluates + * to an object hash, whose keys represent active class names and whose + * values represent the respective state names/globs. + * ui-sref-active will match if the current active state **includes** any of + * the specified state names/globs, even the abstract ones. + * + * Given the following template, with "admin" being an abstract state: + * @example + * ```html + * + *
    +	 * 
    + * Roles + *
    + *
    + * ``` + * + * When the current state is "admin.roles" the "active" class will be applied + * to both the
    and elements. It is important to note that the state + * names/globs passed to ui-sref-active shadow the state provided by ui-sref. + */ + var uiSrefActiveNg1 = ['$state', '$stateParams', '$interpolate', '$transitions', + function $StateRefActiveDirective($state, $stateParams, $interpolate, $transitions) { + return { + restrict: "A", + controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) { + var states = [], activeClasses = {}, activeEqClass, uiSrefActive; + // There probably isn't much point in $observing this + // uiSrefActive and uiSrefActiveEq share the same directive object with some + // slight difference in logic routing + activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope); + try { + uiSrefActive = $scope.$eval($attrs.uiSrefActive); + } + catch (e) { + } + uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope); + if (predicates_1.isObject(uiSrefActive)) { + common_1.forEach(uiSrefActive, function (stateOrName, activeClass) { + if (predicates_1.isString(stateOrName)) { + var ref = parseStateRef(stateOrName, $state.current.name); + addState(ref.state, $scope.$eval(ref.paramExpr), activeClass); + } + }); + } + // Allow uiSref to communicate with uiSrefActive[Equals] + this.$$addStateInfo = function (newState, newParams) { + // we already got an explicit state provided by ui-sref-active, so we + // shadow the one that comes from ui-sref + if (predicates_1.isObject(uiSrefActive) && states.length > 0) { + return; + } + var deregister = addState(newState, newParams, uiSrefActive); + update(); + return deregister; + }; + $scope.$on('$stateChangeSuccess', update); + var updateAfterTransition = ['$transition$', function ($transition$) { $transition$.promise.then(update); }]; + var deregisterFn = $transitions.onStart({}, updateAfterTransition); + $scope.$on('$destroy', deregisterFn); + function addState(stateName, stateParams, activeClass) { + var state = $state.get(stateName, stateContext($element)); + var stateHash = createStateHash(stateName, stateParams); + var stateInfo = { + state: state || { name: stateName }, + params: stateParams, + hash: stateHash + }; + states.push(stateInfo); + activeClasses[stateHash] = activeClass; + return function removeState() { + var idx = states.indexOf(stateInfo); + if (idx !== -1) + states.splice(idx, 1); + }; + } + /** + * @param {string} state + * @param {Object|string} [params] + * @return {string} + */ + function createStateHash(state, params) { + if (!predicates_1.isString(state)) { + throw new Error('state should be a string'); + } + if (predicates_1.isObject(params)) { + return state + common_1.toJson(params); + } + params = $scope.$eval(params); + if (predicates_1.isObject(params)) { + return state + common_1.toJson(params); + } + return state; + } + // Update route state + function update() { + for (var i = 0; i < states.length; i++) { + if (anyMatch(states[i].state, states[i].params)) { + addClass($element, activeClasses[states[i].hash]); + } + else { + removeClass($element, activeClasses[states[i].hash]); + } + if (exactMatch(states[i].state, states[i].params)) { + addClass($element, activeEqClass); + } + else { + removeClass($element, activeEqClass); + } + } + } + function addClass(el, className) { $timeout(function () { el.addClass(className); }); } + function removeClass(el, className) { el.removeClass(className); } + function anyMatch(state, params) { return $state.includes(state.name, params); } + function exactMatch(state, params) { return $state.is(state.name, params); } + update(); + }] + }; + }]; + angular.module('ui.router.state') + .directive('uiSref', uiSrefNg1) + .directive('uiSrefActive', uiSrefActiveNg1) + .directive('uiSrefActiveEq', uiSrefActiveNg1) + .directive('uiState', uiStateNg1); + + +/***/ }, +/* 57 */ +/***/ function(module, exports) { + + /** @module state */ /** for typedoc */ + "use strict"; + /** + * @ngdoc filter + * @name ui.router.state.filter:isState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}. + */ + $IsStateFilter.$inject = ['$state']; + function $IsStateFilter($state) { + var isFilter = function (state, params, options) { + return $state.is(state, params, options); + }; + isFilter.$stateful = true; + return isFilter; + } + exports.$IsStateFilter = $IsStateFilter; + /** + * @ngdoc filter + * @name ui.router.state.filter:includedByState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}. + */ + $IncludedByStateFilter.$inject = ['$state']; + function $IncludedByStateFilter($state) { + var includesFilter = function (state, params, options) { + return $state.includes(state, params, options); + }; + includesFilter.$stateful = true; + return includesFilter; + } + exports.$IncludedByStateFilter = $IncludedByStateFilter; + angular.module('ui.router.state') + .filter('isState', $IsStateFilter) + .filter('includedByState', $IncludedByStateFilter); + + +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + + /** @module ng1_directives */ /** for typedoc */ + "use strict"; + var common_1 = __webpack_require__(3); + var predicates_1 = __webpack_require__(4); + var trace_1 = __webpack_require__(12); + var rejectFactory_1 = __webpack_require__(10); + var hof_1 = __webpack_require__(5); + var strings_1 = __webpack_require__(9); + /** + * `ui-view`: A viewport directive which is filled in by a view from the active state. + * + * @param {string=} name A view name. The name should be unique amongst the other views in the + * same state. You can have views of the same name that live in different states. + * + * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window + * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll + * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you + * scroll ui-view elements into view when they are populated during a state activation. + * + * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) + * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.* + * + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * A view can be unnamed or named. + * @example + * ```html + * + * + *
    + * + * + *
    + * ``` + * + * You can only have one unnamed view within any template (or root html). If you are only using a + * single view and it is unnamed then you can populate it like so: + * ``` + * + *
    + * $stateProvider.state("home", { + * template: "

    HELLO!

    " + * }) + * ``` + * + * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`} + * config property, by name, in this case an empty name: + * ```js + * + * $stateProvider.state("home", { + * views: { + * "": { + * template: "

    HELLO!

    " + * } + * } + * }) + * ``` + * + * But typically you'll only use the views property if you name your view or have more than one view + * in the same template. There's not really a compelling reason to name a view if its the only one, + * but you could if you wanted, like so: + * + * ```html + * + *
    + * ``` + * + * ```js + * + * $stateProvider.state("home", { + * views: { + * "main": { + * template: "

    HELLO!

    " + * } + * } + * }) + * ``` + * + * Really though, you'll use views to set up multiple views: + * ```html + * + *
    + *
    + *
    + * ``` + * + * ```js + * $stateProvider.state("home", { + * views: { + * "": { + * template: "

    HELLO!

    " + * }, + * "chart": { + * template: "" + * }, + * "data": { + * template: "" + * } + * } + * }) + * ``` + * + * Examples for `autoscroll`: + * + * ```html + * + * + * + * + * + * + * + * + * ``` + * + * Resolve data: + * + * The resolved data from the state's `resolve` block is placed on the scope as `$resolve` (this + * can be customized using [[ViewDeclaration.resolveAs]]). This can be then accessed from the template. + * + * Note that when `controllerAs` is being used, `$resolve` is set on the controller instance *after* the + * controller is instantiated. The `$onInit()` hook can be used to perform initialization code which + * depends on `$resolve` data. + * + * @example + * ```js + * + * $stateProvider.state('home', { + * template: '', + * resolve: { + * user: function(UserService) { return UserService.fetchUser(); } + * } + * }); + * ``` + */ + var uiViewNg1 = ['$view', '$animate', '$uiViewScroll', '$interpolate', '$q', + function $ViewDirective($view, $animate, $uiViewScroll, $interpolate, $q) { + function getRenderer(attrs, scope) { + return { + enter: function (element, target, cb) { + if (angular.version.minor > 2) { + $animate.enter(element, null, target).then(cb); + } + else { + $animate.enter(element, null, target, cb); + } + }, + leave: function (element, cb) { + if (angular.version.minor > 2) { + $animate.leave(element).then(cb); + } + else { + $animate.leave(element, cb); + } + } + }; + } + function configsEqual(config1, config2) { + return config1 === config2; + } + var rootData = { + $cfg: { viewDecl: { $context: $view.rootContext() } }, + $uiView: {} + }; + var directive = { + count: 0, + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + compile: function (tElement, tAttrs, $transclude) { + return function (scope, $element, attrs) { + var previousEl, currentEl, currentScope, unregister, onloadExp = attrs.onload || '', autoScrollExp = attrs.autoscroll, renderer = getRenderer(attrs, scope), viewConfig = undefined, inherited = $element.inheritedData('$uiView') || rootData, name = $interpolate(attrs.uiView || attrs.name || '')(scope) || '$default'; + var activeUIView = { + id: directive.count++, + name: name, + fqn: inherited.$uiView.fqn ? inherited.$uiView.fqn + "." + name : name, + config: null, + configUpdated: configUpdatedCallback, + get creationContext() { + return hof_1.parse('$cfg.viewDecl.$context')(inherited); + } + }; + trace_1.trace.traceUiViewEvent("Linking", activeUIView); + function configUpdatedCallback(config) { + if (configsEqual(viewConfig, config)) + return; + trace_1.trace.traceUiViewConfigUpdated(activeUIView, config && config.viewDecl && config.viewDecl.$context); + viewConfig = config; + updateView(config); + } + $element.data('$uiView', { $uiView: activeUIView }); + updateView(); + unregister = $view.registerUiView(activeUIView); + scope.$on("$destroy", function () { + trace_1.trace.traceUiViewEvent("Destroying/Unregistering", activeUIView); + unregister(); + }); + function cleanupLastView() { + if (previousEl) { + trace_1.trace.traceUiViewEvent("Removing (previous) el", previousEl.data('$uiView')); + previousEl.remove(); + previousEl = null; + } + if (currentScope) { + trace_1.trace.traceUiViewEvent("Destroying scope", activeUIView); + currentScope.$destroy(); + currentScope = null; + } + if (currentEl) { + var _viewData_1 = currentEl.data('$uiView'); + trace_1.trace.traceUiViewEvent("Animate out", _viewData_1); + renderer.leave(currentEl, function () { + _viewData_1.$$animLeave.resolve(); + previousEl = null; + }); + previousEl = currentEl; + currentEl = null; + } + } + function updateView(config) { + var newScope = scope.$new(); + trace_1.trace.traceUiViewScopeCreated(activeUIView, newScope); + var animEnter = $q.defer(), animLeave = $q.defer(); + var $uiViewData = { + $cfg: config, + $uiView: activeUIView, + $animEnter: animEnter.promise, + $animLeave: animLeave.promise, + $$animLeave: animLeave + }; + var cloned = $transclude(newScope, function (clone) { + renderer.enter(clone.data('$uiView', $uiViewData), $element, function onUiViewEnter() { + animEnter.resolve(); + if (currentScope) + currentScope.$emit('$viewContentAnimationEnded'); + if (predicates_1.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { + $uiViewScroll(clone); + } + }); + cleanupLastView(); + }); + currentEl = cloned; + currentScope = newScope; + /** + * @ngdoc event + * @name ui.router.state.directive:ui-view#$viewContentLoaded + * @eventOf ui.router.state.directive:ui-view + * @eventType emits on ui-view directive scope + * @description * + * Fired once the view is **loaded**, *after* the DOM is rendered. + * + * @param {Object} event Event object. + */ + currentScope.$emit('$viewContentLoaded', config || viewConfig); + currentScope.$eval(onloadExp); + } + }; + } + }; + return directive; + }]; + $ViewDirectiveFill.$inject = ['$compile', '$controller', '$transitions', '$view', '$timeout']; + /** @hidden */ + function $ViewDirectiveFill($compile, $controller, $transitions, $view, $timeout) { + var getControllerAs = hof_1.parse('viewDecl.controllerAs'); + var getResolveAs = hof_1.parse('viewDecl.resolveAs'); + var getResolveContext = hof_1.parse('node.resolveContext'); + return { + restrict: 'ECA', + priority: -400, + compile: function (tElement) { + var initial = tElement.html(); + return function (scope, $element) { + var data = $element.data('$uiView'); + if (!data) + return; + var cfg = data.$cfg || { viewDecl: {} }; + $element.html(cfg.template || initial); + trace_1.trace.traceUiViewFill(data.$uiView, $element.html()); + var link = $compile($element.contents()); + var controller = cfg.controller; + var controllerAs = getControllerAs(cfg); + var resolveAs = getResolveAs(cfg); + var resolveCtx = getResolveContext(cfg); + var locals = resolveCtx && common_1.map(resolveCtx.getResolvables(), function (r) { return r.data; }); + scope[resolveAs] = locals; + if (controller) { + var controllerInstance = $controller(controller, common_1.extend({}, locals, { $scope: scope, $element: $element })); + if (controllerAs) { + scope[controllerAs] = controllerInstance; + scope[controllerAs][resolveAs] = locals; + } + // TODO: Use $view service as a central point for registering component-level hooks + // Then, when a component is created, tell the $view service, so it can invoke hooks + // $view.componentLoaded(controllerInstance, { $scope: scope, $element: $element }); + // scope.$on('$destroy', () => $view.componentUnloaded(controllerInstance, { $scope: scope, $element: $element })); + $element.data('$ngControllerController', controllerInstance); + $element.children().data('$ngControllerController', controllerInstance); + registerControllerCallbacks($transitions, controllerInstance, scope, cfg); + } + // Wait for the component to appear in the DOM + if (predicates_1.isString(cfg.viewDecl.component)) { + var cmp_1 = cfg.viewDecl.component; + var kebobName_1 = strings_1.kebobString(cmp_1); + var getComponentController = function () { + var directiveEl = [].slice.call($element[0].children) + .filter(function (el) { return el && el.tagName && el.tagName.toLowerCase() === kebobName_1; }); + return directiveEl && angular.element(directiveEl).data("$" + cmp_1 + "Controller"); + }; + var deregisterWatch_1 = scope.$watch(getComponentController, function (ctrlInstance) { + if (!ctrlInstance) + return; + registerControllerCallbacks($transitions, ctrlInstance, scope, cfg); + deregisterWatch_1(); + }); + } + link(scope); + }; + } + }; + } + /** @hidden */ + var hasComponentImpl = typeof angular.module('ui.router')['component'] === 'function'; + /** @hidden TODO: move these callbacks to $view and/or `/hooks/components.ts` or something */ + function registerControllerCallbacks($transitions, controllerInstance, $scope, cfg) { + // Call $onInit() ASAP + if (predicates_1.isFunction(controllerInstance.$onInit) && !(cfg.viewDecl.component && hasComponentImpl)) + controllerInstance.$onInit(); + var hookOptions = { bind: controllerInstance }; + // Add component-level hook for onParamsChange + if (predicates_1.isFunction(controllerInstance.uiOnParamsChanged)) { + // Fire callback on any successful transition + var paramsUpdated_1 = function ($transition$) { + var ctx = cfg.node.resolveContext; + var viewCreationTrans = ctx.getResolvables()['$transition$'].data; + // Exit early if the $transition$ is the same as the view was created within. + // Exit early if the $transition$ will exit the state the view is for. + if ($transition$ === viewCreationTrans || $transition$.exiting().indexOf(cfg.node.state.self) !== -1) + return; + var toParams = $transition$.params("to"); + var fromParams = $transition$.params("from"); + var toSchema = $transition$.treeChanges().to.map(function (node) { return node.paramSchema; }).reduce(common_1.unnestR, []); + var fromSchema = $transition$.treeChanges().from.map(function (node) { return node.paramSchema; }).reduce(common_1.unnestR, []); + // Find the to params that have different values than the from params + var changedToParams = toSchema.filter(function (param) { + var idx = fromSchema.indexOf(param); + return idx === -1 || !fromSchema[idx].type.equals(toParams[param.id], fromParams[param.id]); + }); + // Only trigger callback if a to param has changed or is new + if (changedToParams.length) { + var changedKeys_1 = changedToParams.map(function (x) { return x.id; }); + // Filter the params to only changed/new to params. `$transition$.params()` may be used to get all params. + controllerInstance.uiOnParamsChanged(common_1.filter(toParams, function (val, key) { return changedKeys_1.indexOf(key) !== -1; }), $transition$); + } + }; + $scope.$on('$destroy', $transitions.onSuccess({}, ['$transition$', paramsUpdated_1]), hookOptions); + // Fire callback on any IGNORED transition + var onDynamic = function ($error$, $transition$) { + if ($error$.type === rejectFactory_1.RejectType.IGNORED) + paramsUpdated_1($transition$); + }; + $scope.$on('$destroy', $transitions.onError({}, ['$error$', '$transition$', onDynamic]), hookOptions); + } + // Add component-level hook for uiCanExit + if (predicates_1.isFunction(controllerInstance.uiCanExit)) { + var criteria = { exiting: cfg.node.state.name }; + $scope.$on('$destroy', $transitions.onBefore(criteria, controllerInstance.uiCanExit, hookOptions)); + } + } + angular.module('ui.router.state').directive('uiView', uiViewNg1); + angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill); + + +/***/ }, +/* 59 */ +/***/ function(module, exports) { + + "use strict"; + /** + * @ngdoc object + * @name ui.router.state.$uiViewScrollProvider + * + * @description + * Provider that returns the {@link ui.router.state.$uiViewScroll} service function. + */ + function $ViewScrollProvider() { + var useAnchorScroll = false; + /** + * @ngdoc function + * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll + * @methodOf ui.router.state.$uiViewScrollProvider + * + * @description + * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for + * scrolling based on the url anchor. + */ + this.useAnchorScroll = function () { + useAnchorScroll = true; + }; + /** + * @ngdoc object + * @name ui.router.state.$uiViewScroll + * + * @requires $anchorScroll + * @requires $timeout + * + * @description + * When called with a jqLite element, it scrolls the element into view (after a + * `$timeout` so the DOM has time to refresh). + * + * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor, + * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}. + */ + this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) { + if (useAnchorScroll) { + return $anchorScroll; + } + return function ($element) { + return $timeout(function () { + $element[0].scrollIntoView(); + }, 0, false); + }; + }]; + } + angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider); + + +/***/ } +/******/ ]) +}); +; +//# sourceMappingURL=angular-ui-router.js.map \ No newline at end of file diff --git a/static/js/angular-ui-router.min.js b/static/js/angular-ui-router.min.js index f1b0e35..a558fed 100644 --- a/static/js/angular-ui-router.min.js +++ b/static/js/angular-ui-router.min.js @@ -1,8 +1,10 @@ -/** +/*! * State-based routing for AngularJS - * @version v0.2.18 - * @link http://angular-ui.github.com/ + * @version v1.0.0-alpha.4 + * @link http://angular-ui.github.com/ui-router * @license MIT License, http://www.opensource.org/licenses/MIT */ -"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return R(new(R(function(){},{prototype:a})),b)}function e(a){return Q(arguments,function(b){b!==a&&Q(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]!==b.path[d])break;c.push(a.path[d])}return c}function g(a){if(Object.keys)return Object.keys(a);var b=[];return Q(a,function(a,c){b.push(c)}),b}function h(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 i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l]&&i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return R({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,N(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);Q(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return O(a)&&a.then&&a.$$promises}if(!O(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return Q(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!L(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;Q(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!O(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=l;var n=a.defer(),r=n.promise,s=r.$$promises={},t=R({},d),u=1+q.length/3,v=!1;if(L(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,m(f.$$inheritedValues,p)),R(s,f.$$promises),f.$$values?(v=e(t,m(f.$$values,p)),r.$$inheritedValues=m(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=m(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function q(a,b,c){this.fromConfig=function(a,b,c){return L(a.template)?this.fromString(a.template,b):L(a.templateUrl)?this.fromUrl(a.templateUrl,b):L(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return M(a)?a(b):a},this.fromUrl=function(c,d){return M(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function r(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+([-.]+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new U.Param(b,c,d,e),p[b]}function g(a,b,c,d){var e=["",""],f=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return f;switch(c){case!1:e=["(",")"+(d?"?":"")];break;case!0:f=f.replace(/\/$/,""),e=["(?:/(",")|/)?"];break;default:e=["("+c+"|",")?"]}return f+e[0]+b+e[1]}function h(e,f){var g,h,i,j,k;return g=e[2]||e[3],k=b.params[g],i=a.substring(m,e.index),h=f?e[4]:e[4]||("*"==e[1]?".*":null),h&&(j=U.type(h)||d(U.type("string"),{pattern:new RegExp(h,b.caseInsensitive?"i":c)})),{id:g,regexp:h,segment:i,type:j,cfg:k}}b=R({params:{}},O(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new U.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash,s.isOptional),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function s(a){R(this,a)}function t(){function a(a){return null!=a?a.toString().replace(/~/g,"~~").replace(/\//g,"~2F"):a}function e(a){return null!=a?a.toString().replace(/~2F/g,"/").replace(/~~/g,"~"):a}function f(){return{strict:p,caseInsensitive:m}}function i(a){return M(a)||P(a)&&M(a[a.length-1])}function j(){for(;w.length;){var a=w.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(u[a.name],l.invoke(a.def))}}function k(a){R(this,a||{})}U=this;var l,m=!1,p=!0,q=!1,u={},v=!0,w=[],x={string:{encode:a,decode:e,is:function(a){return null==a||!L(a)||"string"==typeof a},pattern:/[^\/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return L(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^\/]*/},any:{encode:b.identity,decode:b.identity,equals:b.equals,pattern:/.*/}};t.$$getDefaultValue=function(a){if(!i(a.value))return a.value;if(!l)throw new Error("Injectable functions cannot be called at configuration time");return l.invoke(a.value)},this.caseInsensitive=function(a){return L(a)&&(m=a),m},this.strictMode=function(a){return L(a)&&(p=a),p},this.defaultSquashPolicy=function(a){if(!L(a))return q;if(a!==!0&&a!==!1&&!N(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return q=a,a},this.compile=function(a,b){return new r(a,R(f(),b))},this.isMatcher=function(a){if(!O(a))return!1;var b=!0;return Q(r.prototype,function(c,d){M(c)&&(b=b&&L(a[d])&&M(a[d]))}),b},this.type=function(a,b,c){if(!L(b))return u[a];if(u.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return u[a]=new s(R({name:a},b)),c&&(w.push({name:a,def:c}),v||j()),this},Q(x,function(a,b){u[b]=new s(R({name:b},a))}),u=d(u,{}),this.$get=["$injector",function(a){return l=a,v=!1,j(),Q(x,function(a,b){u[b]||(u[b]=new s(a))}),this}],this.Param=function(a,d,e,f){function j(a){var b=O(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=i(a.value)?a.value:function(){return a.value},a}function k(c,d,e){if(c.type&&d)throw new Error("Param '"+a+"' has two type configurations.");return d?d:c.type?b.isString(c.type)?u[c.type]:c.type instanceof s?c.type:new s(c.type):"config"===e?u.any:u.string}function m(){var b={array:"search"===f?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return R(b,c,e).array}function p(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!L(c)||null==c)return q;if(c===!0||N(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function r(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=P(a.replace)?a.replace:[],N(e)&&f.push({from:e,to:c}),g=o(f,function(a){return a.from}),n(i,function(a){return-1===h(g,a.from)}).concat(f)}function t(){if(!l)throw new Error("Injectable functions cannot be called at configuration time");var a=l.invoke(e.$$fn);if(null!==a&&a!==c&&!x.type.is(a))throw new Error("Default value ("+a+") for parameter '"+x.id+"' is not an instance of Type ("+x.type.name+")");return a}function v(a){function b(a){return function(b){return b.from===a}}function c(a){var c=o(n(x.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),L(a)?x.type.$normalize(a):t()}function w(){return"{Param:"+a+" "+d+" squash: '"+A+"' optional: "+z+"}"}var x=this;e=j(e),d=k(e,d,f);var y=m();d=y?d.$asArray(y,"search"===f):d,"string"!==d.name||y||"path"!==f||e.value!==c||(e.value="");var z=e.value!==c,A=p(e,z),B=r(e,y,z,A);R(this,{id:a,type:d,location:f,array:y,squash:A,replace:B,isOptional:z,value:v,dynamic:c,config:e,toString:w})},k.prototype={$$new:function(){return d(this,R(new k,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(k.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),Q(b,function(b){Q(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return Q(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return Q(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var d,e,f,g,h,i=this.$$keys();for(d=0;de;e++)if(b(j[e]))return;k&&b(k)}}function o(){return i=i||e.$on("$locationChangeSuccess",n)}var p,q=g.baseHref(),r=d.url();return l||o(),{sync:function(){n()},listen:function(){return o()},update:function(a){return a?void(r=d.url()):void(d.url()!==r&&(d.url(r),d.replace()))},push:function(a,b,e){var f=a.format(b||{});null!==f&&b&&b["#"]&&(f+="#"+b["#"]),d.url(f),p=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled),g=g&&h.history;var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),null!==i&&e&&e["#"]&&(i+="#"+e["#"]),i=m(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!M(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(N(a)){var b=a;a=function(){return b}}else if(!M(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=N(b);if(N(a)&&(a=d.compile(a)),!h&&!M(b)&&!P(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),R(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:N(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),R(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser","$sniffer"]}function v(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function m(a,b){if(!a)return c;var d=N(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=m(b);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=z[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function n(a,b){A[a]||(A[a]=[]),A[a].push(b)}function p(a){for(var b=A[a]||[];b.length;)q(b.shift())}function q(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!N(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(z.hasOwnProperty(c))throw new Error("State '"+c+"' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):N(b.parent)?b.parent:O(b.parent)&&N(b.parent.name)?b.parent.name:"";if(e&&!z[e])return n(e,b.self);for(var f in C)M(C[f])&&(b[f]=C[f](b,C.$delegates[f]));return z[c]=b,!b[B]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){y.$current.navigable==b&&j(a,c)||y.transitionTo(b,a,{inherit:!0,location:!1})}]),p(c),b}function r(a){return a.indexOf("*")>-1}function s(a){for(var b=a.split("."),c=y.$current.name.split("."),d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return"**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length?!1:c.join("")===b.join("")}function t(a,b){return N(a)&&!L(b)?C[a]:M(b)&&N(a)?(C[a]&&!C.$delegates[a]&&(C.$delegates[a]=C[a]),C[a]=b,this):this}function u(a,b){return O(a)?b=a:b.name=a,q(b),this}function v(a,e,f,h,l,n,p,q,t){function u(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),D;if(!g.retry)return null;if(f.$retry)return p.update(),E;var h=y.transition=e.when(g.retry);return h.then(function(){return h!==y.transition?A:(b.options.$retry=!0,y.transitionTo(b.to,b.toParams,b.options))},function(){return D}),p.update(),h}function v(a,c,d,g,i,j){function m(){var c=[];return Q(a.views,function(d,e){var g=d.resolve&&d.resolve!==a.resolve?d.resolve:{};g.$template=[function(){return f.load(e,{view:d,locals:i.globals,params:n,notify:j.notify})||""}],c.push(l.resolve(g,i.globals,i.resolve,a).then(function(c){if(M(d.controllerProvider)||P(d.controllerProvider)){var f=b.extend({},g,i.globals);c.$$controller=h.invoke(d.controllerProvider,null,f)}else c.$$controller=d.controller;c.$$state=a,c.$$controllerAs=d.controllerAs,i[e]=c}))}),e.all(c).then(function(){return i.globals})}var n=d?c:k(a.params.$$keys(),c),o={$stateParams:n};i.resolve=l.resolve(a.resolve,o,i.resolve,a);var p=[i.resolve.then(function(a){i.globals=a})];return g&&p.push(g),e.all(p).then(m).then(function(a){return i})}var A=e.reject(new Error("transition superseded")),C=e.reject(new Error("transition prevented")),D=e.reject(new Error("transition aborted")),E=e.reject(new Error("transition failed"));return x.locals={resolve:null,globals:{$stateParams:{}}},y={params:{},current:x.self,$current:x,transition:null},y.reload=function(a){return y.transitionTo(y.current,n,{reload:a||!0,inherit:!1,notify:!0})},y.go=function(a,b,c){return y.transitionTo(a,b,R({inherit:!0,relative:y.$current},c))},y.transitionTo=function(b,c,f){c=c||{},f=R({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=y.$current,l=y.params,o=j.path,q=m(b,f.relative),r=c["#"];if(!L(q)){var s={to:b,toParams:c,options:f},t=u(s,j.self,l,f);if(t)return t;if(b=s.to,c=s.toParams,f=s.options,q=m(b,f.relative),!L(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[B])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(n,c||{},y.$current,q)),!q.params.$$validates(c))return E;c=q.params.$$values(c),b=q;var z=b.path,D=0,F=z[D],G=x.locals,H=[];if(f.reload){if(N(f.reload)||O(f.reload)){if(O(f.reload)&&!f.reload.name)throw new Error("Invalid reload state object");var I=f.reload===!0?o[0]:m(f.reload);if(f.reload&&!I)throw new Error("No such reload state '"+(N(f.reload)?f.reload:f.reload.name)+"'");for(;F&&F===o[D]&&F!==I;)G=H[D]=F.locals,D++,F=z[D]}}else for(;F&&F===o[D]&&F.ownParams.$$equals(c,l);)G=H[D]=F.locals,D++,F=z[D];if(w(b,c,j,l,G,f))return r&&(c["#"]=r),y.params=c,S(y.params,n),S(k(b.params.$$keys(),n),b.locals.globals.$stateParams),f.location&&b.navigable&&b.navigable.url&&(p.push(b.navigable.url,c,{$$avoidResync:!0,replace:"replace"===f.location}),p.update(!0)),y.transition=null,e.when(y.current);if(c=k(b.params.$$keys(),c||{}),r&&(c["#"]=r),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,l,f).defaultPrevented)return a.$broadcast("$stateChangeCancel",b.self,c,j.self,l),null==y.transition&&p.update(),C;for(var J=e.when(G),K=D;K=D;d--)g=o[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d=4?!!j.enabled(a):1===V&&W>=2?!!j.enabled():!!i}var e={enter:function(a,b,c){b.after(a),c()},leave:function(a,b){a.remove(),b()}};if(a.noanimation)return e;if(j)return{enter:function(a,c,f){d(a)?b.version.minor>2?j.enter(a,null,c).then(f):j.enter(a,null,c,f):e.enter(a,c,f)},leave:function(a,c){d(a)?b.version.minor>2?j.leave(a).then(c):j.leave(a,c):e.leave(a,c)}};if(i){var f=i&&i(c,a);return{enter:function(a,b,c){f.enter(a,null,b),c()},leave:function(a,b){f.leave(a),b()}}}return e}var h=f(),i=h("$animator"),j=h("$animate"),k={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,f,h){return function(c,f,i){function j(){function a(){b&&b.remove(),c&&c.$destroy()}var b=l,c=n;c&&(c._willBeDestroyed=!0),m?(r.leave(m,function(){a(),l=null}),l=m):(a(),l=null),m=null,n=null}function k(g){var k,l=A(c,i,f,e),s=l&&a.$current&&a.$current.locals[l];if((g||s!==o)&&!c._willBeDestroyed){k=c.$new(),o=a.$current.locals[l],k.$emit("$viewContentLoading",l);var t=h(k,function(a){r.enter(a,f,function(){n&&n.$emit("$viewContentAnimationEnded"),(b.isDefined(q)&&!q||c.$eval(q))&&d(a)}),j()});m=t,n=k,n.$emit("$viewContentLoaded",l),n.$eval(p)}}var l,m,n,o,p=i.onload||"",q=i.autoscroll,r=g(i,c);c.$on("$stateChangeSuccess",function(){k(!1)}),k(!0)}}};return k}function z(a,b,c,d){return{restrict:"ECA",priority:-400,compile:function(e){var f=e.html();return function(e,g,h){var i=c.$current,j=A(e,h,g,d),k=i&&i.locals[j];if(k){g.data("$uiView",{name:j,state:k.$$state}),g.html(k.$template?k.$template:f);var l=a(g.contents());if(k.$$controller){k.$scope=e,k.$element=g;var m=b(k.$$controller,k);k.$$controllerAs&&(e[k.$$controllerAs]=m),g.data("$ngControllerController",m),g.children().data("$ngControllerController",m)}l(e)}}}}}function A(a,b,c,d){var e=d(b.uiView||b.name||"")(a),f=c.inheritedData("$uiView");return e.indexOf("@")>=0?e:e+"@"+(f?f.state.name:"")}function B(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function C(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function D(a){var b="[object SVGAnimatedString]"===Object.prototype.toString.call(a.prop("href")),c="FORM"===a[0].nodeName;return{attr:c?"action":b?"xlink:href":"href",isAnchor:"A"===a.prop("tagName").toUpperCase(),clickable:!c}}function E(a,b,c,d,e){return function(f){var g=f.which||f.button,h=e();if(!(g>1||f.ctrlKey||f.metaKey||f.shiftKey||a.attr("target"))){var i=c(function(){b.go(h.state,h.params,h.options)});f.preventDefault();var j=d.isAnchor&&!h.href?1:0;f.preventDefault=function(){j--<=0&&c.cancel(i)}}}}function F(a,b){return{relative:C(a)||b.$current,inherit:!0}}function G(a,c){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(d,e,f,g){var h=B(f.uiSref,a.current.name),i={state:h.state,href:null,params:null},j=D(e),k=g[1]||g[0];i.options=R(F(e,a),f.uiSrefOpts?d.$eval(f.uiSrefOpts):{});var l=function(c){c&&(i.params=b.copy(c)),i.href=a.href(h.state,i.params,i.options),k&&k.$$addStateInfo(h.state,i.params),null!==i.href&&f.$set(j.attr,i.href)};h.paramExpr&&(d.$watch(h.paramExpr,function(a){a!==i.params&&l(a)},!0),i.params=b.copy(d.$eval(h.paramExpr))),l(),j.clickable&&e.bind("click",E(e,a,c,j,function(){return i}))}}}function H(a,b){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(c,d,e,f){function g(b){l.state=b[0],l.params=b[1],l.options=b[2],l.href=a.href(l.state,l.params,l.options),i&&i.$$addStateInfo(l.state,l.params),l.href&&e.$set(h.attr,l.href)}var h=D(d),i=f[1]||f[0],j=[e.uiState,e.uiStateParams||null,e.uiStateOpts||null],k="["+j.map(function(a){return a||"null"}).join(", ")+"]",l={state:null,params:null,options:null,href:null};c.$watch(k,g,!0),g(c.$eval(k)),h.clickable&&d.bind("click",E(d,a,b,h,function(){return l}))}}}function I(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(b,d,e,f){function g(b,c,e){var f=a.get(b,C(d)),g=h(b,c);p.push({state:f||{name:b},params:c,hash:g}),q[g]=e}function h(a,c){if(!N(a))throw new Error("state should be a string");return O(c)?a+T(c):(c=b.$eval(c),O(c)?a+T(c):a)}function i(){for(var a=0;a0||(g(a,b,o),i())},b.$on("$stateChangeSuccess",i),i()}]}}function J(a){var b=function(b,c){return a.is(b,c)};return b.$stateful=!0,b}function K(a){var b=function(b,c,d){return a.includes(b,c,d)};return b.$stateful=!0,b}var L=b.isDefined,M=b.isFunction,N=b.isString,O=b.isObject,P=b.isArray,Q=b.forEach,R=b.extend,S=b.copy,T=b.toJson;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"]),p.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",p),q.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",q);var U;r.prototype.concat=function(a,b){var c={caseInsensitive:U.caseInsensitive(),strict:U.strictMode(),squash:U.defaultSquashPolicy()};return new r(this.sourcePath+a+this.sourceSearch,R(c,b),this)},r.prototype.toString=function(){return this.source},r.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/g,"-")}var d=b(a).split(/-(?!\\)/),e=o(d,b);return o(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");var l,m;for(e=0;j>e;e++){for(g=h[e],l=this.params[g],m=d[e+1],f=0;fe;e++){for(g=h[e],k[g]=this.params[g].value(b[g]),l=this.params[g],m=b[g],f=0;ff;f++){var k=h>f,l=d[f],m=e[l],n=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),n),q=p?m.squash:!1,r=m.type.encode(n);if(k){var s=c[f+1],t=f+1===h;if(q===!1)null!=r&&(j+=P(r)?o(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var u=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(u)[1]}else N(q)&&(j+=q+s);t&&m.squash===!0&&"/"===j.slice(-1)&&(j=j.slice(0,-1))}else{if(null==r||p&&q!==!1)continue;if(P(r)||(r=[r]),0===r.length)continue;r=o(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},s.prototype.is=function(a,b){return!0},s.prototype.encode=function(a,b){return a},s.prototype.decode=function(a,b){return a},s.prototype.equals=function(a,b){return a==b},s.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},s.prototype.pattern=/.*/,s.prototype.toString=function(){return"{Type:"+this.name+"}"},s.prototype.$normalize=function(a){return this.is(a)?a:this.decode(a)},s.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return P(a)?a:L(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){if(P(c)&&0===c.length)return c;c=e(c);var d=o(c,a);return b===!0?0===n(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g=0&&t.splice(n,1),t}),e.defaults=i,e.merge=o,e.mergeR=function(t,n){return e.extend(t,n)},e.ancestors=a,e.equalForKeys=s,e.pick=c,e.omit=l,e.pluck=f,e.filter=p,e.find=h,e.mapObj=v,e.map=v,e.values=function(t){return Object.keys(t).map(function(e){return t[e]})},e.allTrueR=function(t,e){return t&&e},e.anyTrueR=function(t,e){return t||e},e.unnestR=function(t,e){return t.concat(e)},e.flattenR=function(t,n){return k.isArray(n)?t.concat(n.reduce(e.flattenR,[])):d(t,n)},e.unnest=function(t){return t.reduce(e.unnestR,[])},e.flatten=function(t){return t.reduce(e.flattenR,[])},e.assertPredicate=m,e.pairs=function(t){return Object.keys(t).map(function(e){return[e,t[e]]})},e.arrayTuples=g,e.applyPairs=y,e.tail=w},function(t,e,n){"use strict";function r(t){if(e.isArray(t)&&t.length){var n=t.slice(0,-1),r=t.slice(-1);return!(n.filter(i.not(e.isString)).length||r.filter(i.not(e.isFunction)).length)}return e.isFunction(t)}var i=n(5),o=Object.prototype.toString,a=function(t){return function(e){return typeof e===t}};e.isUndefined=a("undefined"),e.isDefined=i.not(e.isUndefined),e.isNull=function(t){return null===t},e.isFunction=a("function"),e.isNumber=a("number"),e.isString=a("string"),e.isObject=function(t){return null!==t&&"object"==typeof t},e.isArray=Array.isArray,e.isDate=function(t){return"[object Date]"===o.call(t)},e.isRegExp=function(t){return"[object RegExp]"===o.call(t)},e.isInjectable=r,e.isPromise=i.and(e.isObject,i.pipe(i.prop("then"),e.isFunction))},function(t,e){"use strict";function n(t){function e(n){return n.length>=r?t.apply(null,n):function(){return e(n.concat([].slice.apply(arguments)))}}var n=[].slice.apply(arguments,[1]),r=t.length;return e(n)}function r(){var t=arguments,e=t.length-1;return function(){for(var n=e,r=t[e].apply(this,arguments);n--;)r=t[n].call(this,r);return r}}function i(){for(var t=[],e=0;en;n++)"*"===this.glob[n]&&(e[n]="*");return"**"===this.glob[0]&&(e=e.slice(e.indexOf(this.glob[1])),e.unshift("**")),"**"===this.glob[this.glob.length-1]&&(e.splice(e.indexOf(this.glob[this.glob.length-2])+1,Number.MAX_VALUE),e.push("**")),this.glob.length!=e.length?!1:e.join("")===this.glob.join("")},t.is=function(t){return t.indexOf("*")>-1},t.fromString=function(e){return this.is(e)?new t(e):null},t}();e.Glob=n},function(t,e){"use strict";var n=function(){function t(t,e){void 0===t&&(t=[]),void 0===e&&(e=null),this._items=t,this._limit=e}return t.prototype.enqueue=function(t){var e=this._items;return e.push(t),this._limit&&e.length>this._limit&&e.shift(),t},t.prototype.dequeue=function(){return this.size()?this._items.splice(0,1)[0]:void 0},t.prototype.clear=function(){var t=this._items;return this._items=[],t},t.prototype.size=function(){return this._items.length},t.prototype.remove=function(t){var e=this._items.indexOf(t);return e>-1&&this._items.splice(e,1)[0]},t.prototype.peekTail=function(){return this._items[this._items.length-1]},t.prototype.peekHead=function(){return this.size()?this._items[0]:void 0},t}();e.Queue=n},function(t,e,n){"use strict";function r(t,e){return e.length<=t?e:e.substr(0,t-3)+"..."}function i(t,e){for(;e.length "+c+"'"+l+"'"+f+" )"},t}();e.Transition=g},function(t,e,n){"use strict";function r(t){return t?"ui-view id#"+t.id+", contextual name '"+t.name+"@"+t.creationContext+"', fqn: '"+t.fqn+"'":"ui-view (defunct)"}function i(t){return a.isNumber(t)?c[t]:c[c[t]]}var o=n(5),a=n(4),s=n(9),u=function(t){return"ViewConfig targeting ui-view: '"+t.viewDecl.$uiViewName+"@"+t.viewDecl.$uiViewContextAnchor+"', context: '"+t.viewDecl.$context.name+"'"};!function(t){t[t.RESOLVE=0]="RESOLVE",t[t.TRANSITION=1]="TRANSITION",t[t.HOOK=2]="HOOK",t[t.INVOKE=3]="INVOKE",t[t.UIVIEW=4]="UIVIEW",t[t.VIEWCONFIG=5]="VIEWCONFIG"}(e.Category||(e.Category={}));var c=e.Category,l=function(){function t(){this._enabled={},this.approximateDigests=0}return t.prototype._set=function(t,e){var n=this;e.length||(e=Object.keys(c).filter(function(t){return isNaN(parseInt(t,10))}).map(function(t){return c[t]})),e.map(i).forEach(function(e){return n._enabled[e]=t})},t.prototype.enable=function(){for(var t=[],e=0;e "+r)}},t.prototype.traceTransitionIgnored=function(t){if(this.enabled(c.TRANSITION)){var e=t.$id,n=this.approximateDigests,r=s.stringify(t);console.log("Transition #"+e+" Digest #"+n+": Ignored <> "+r)}},t.prototype.traceHookInvocation=function(t,e){if(this.enabled(c.HOOK)){var n=o.parse("transition.$id")(e),r=this.approximateDigests,i=o.parse("traceData.hookType")(e)||"internal",a=o.parse("traceData.context.state.name")(e)||o.parse("traceData.context")(e)||"unknown",u=s.functionToString(t.fn);console.log("Transition #"+n+" Digest #"+r+": Hook -> "+i+" context: "+a+", "+s.maxLength(200,u))}},t.prototype.traceHookResult=function(t,e,n){if(this.enabled(c.HOOK)){var r=o.parse("transition.$id")(n),i=this.approximateDigests,a=s.stringify(t),u=s.stringify(e);console.log("Transition #"+r+" Digest #"+i+": <- Hook returned: "+s.maxLength(200,a)+", transition result: "+s.maxLength(200,u))}},t.prototype.traceResolvePath=function(t,e){if(this.enabled(c.RESOLVE)){var n=o.parse("transition.$id")(e),r=this.approximateDigests,i=t&&t.toString(),a=e&&e.resolvePolicy;console.log("Transition #"+n+" Digest #"+r+": Resolving "+i+" ("+a+")")}},t.prototype.traceResolvePathElement=function(t,e,n){if(this.enabled(c.RESOLVE)&&e.length){var r=o.parse("transition.$id")(n),i=this.approximateDigests,a=Object.keys(e).join(", "),s=t&&t.toString(),u=n&&n.resolvePolicy;console.log("Transition #"+r+" Digest #"+i+": Resolve "+s+" resolvables: ["+a+"] ("+u+")")}},t.prototype.traceResolveResolvable=function(t,e){if(this.enabled(c.RESOLVE)){var n=o.parse("transition.$id")(e),r=this.approximateDigests,i=t&&t.toString();console.log("Transition #"+n+" Digest #"+r+": Resolving -> "+i)}},t.prototype.traceResolvableResolved=function(t,e){if(this.enabled(c.RESOLVE)){var n=o.parse("transition.$id")(e),r=this.approximateDigests,i=t&&t.toString(),a=s.stringify(t.data);console.log("Transition #"+n+" Digest #"+r+": <- Resolved "+i+" to: "+s.maxLength(200,a))}},t.prototype.tracePathElementInvoke=function(t,e,n,r){if(this.enabled(c.INVOKE)){var i=o.parse("transition.$id")(r),a=this.approximateDigests,u=t&&t.state&&t.state.toString(),l=s.functionToString(e);console.log("Transition #"+i+" Digest #"+a+": Invoke "+r.when+": context: "+u+" "+s.maxLength(200,l))}},t.prototype.traceError=function(t,e){if(this.enabled(c.TRANSITION)){var n=e.$id,r=this.approximateDigests,i=s.stringify(e);console.log("Transition #"+n+" Digest #"+r+": <- Rejected "+i+", reason: "+t)}},t.prototype.traceSuccess=function(t,e){if(this.enabled(c.TRANSITION)){var n=e.$id,r=this.approximateDigests,i=t.name,o=s.stringify(e);console.log("Transition #"+n+" Digest #"+r+": <- Success "+o+", final state: "+i)}},t.prototype.traceUiViewEvent=function(t,e,n){void 0===n&&(n=""),this.enabled(c.UIVIEW)&&console.log("ui-view: "+s.padString(30,t)+" "+r(e)+n)},t.prototype.traceUiViewConfigUpdated=function(t,e){this.enabled(c.UIVIEW)&&this.traceUiViewEvent("Updating",t," with ViewConfig from context='"+e+"'")},t.prototype.traceUiViewScopeCreated=function(t,e){this.enabled(c.UIVIEW)&&this.traceUiViewEvent("Created scope for",t,", scope #"+e.$id)},t.prototype.traceUiViewFill=function(t,e){this.enabled(c.UIVIEW)&&this.traceUiViewEvent("Fill",t," with: "+s.maxLength(200,e))},t.prototype.traceViewServiceEvent=function(t,e){this.enabled(c.VIEWCONFIG)&&console.log("$view.ViewConfig: "+t+" "+u(e))},t.prototype.traceViewServiceUiViewEvent=function(t,e){this.enabled(c.VIEWCONFIG)&&console.log("$view.ViewConfig: "+t+" "+r(e))},t}();e.Trace=l;var f=new l;e.trace=f},function(t,e,n){"use strict";function r(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}r(n(14)),r(n(15)),r(n(10)),r(n(11)),r(n(16)),r(n(43))},function(t,e,n){"use strict";function r(t){return void 0===t&&(t=!1),function(e,n){var r=t?-1:1,i=(e.node.state.path.length-n.node.state.path.length)*r;return 0!==i?i:n.hook.priority-e.hook.priority}}var i=n(3),o=n(4),a=n(13),s=function(){function t(t,e,n){var o=this;this.$transitions=t,this.transition=e,this.baseHookOptions=n,this.getOnBeforeHooks=function(){return o._buildNodeHooks("onBefore","to",r(),void 0,{async:!1})},this.getOnStartHooks=function(){return o._buildNodeHooks("onStart","to",r())},this.getOnExitHooks=function(){return o._buildNodeHooks("onExit","exiting",r(!0),function(t){return{$state$:t.state}})},this.getOnRetainHooks=function(){return o._buildNodeHooks("onRetain","retained",r(),function(t){return{$state$:t.state}})},this.getOnEnterHooks=function(){return o._buildNodeHooks("onEnter","entering",r(),function(t){return{$state$:t.state}})},this.getOnFinishHooks=function(){return o._buildNodeHooks("onFinish","to",r(),function(t){return{$treeChanges$:o.treeChanges}})},this.getOnSuccessHooks=function(){return o._buildNodeHooks("onSuccess","to",r(),void 0,{async:!1,rejectIfSuperseded:!1})},this.getOnErrorHooks=function(){return o._buildNodeHooks("onError","to",r(),void 0,{async:!1,rejectIfSuperseded:!1})},this.treeChanges=e.treeChanges(),this.toState=i.tail(this.treeChanges.to).state,this.fromState=i.tail(this.treeChanges.from).state,this.transitionOptions=e.options()}return t.prototype.asyncHooks=function(){var t=this.getOnStartHooks(),e=this.getOnExitHooks(),n=this.getOnRetainHooks(),r=this.getOnEnterHooks(),o=this.getOnFinishHooks(),a=[t,e,n,r,o];return a.reduce(i.unnestR,[]).filter(i.identity)},t.prototype._buildNodeHooks=function(t,e,n,r,o){var s=this;void 0===r&&(r=function(t){return{}});var u=this._matchingHooks(t,this.treeChanges);if(!u)return[];var c=function(n){var u=n.matches(s.treeChanges),c=u[e];return c.map(function(e){var u=i.extend({bind:n.bind,traceData:{hookType:t,context:e}},s.baseHookOptions,o),c=new a.TransitionHook(n.callback,r(e),e.resolveContext,u);return{hook:n,node:e,transitionHook:c}})};return u.map(c).reduce(i.unnestR,[]).sort(n).map(function(t){return t.transitionHook})},t.prototype._matchingHooks=function(t,e){return[this.transition,this.$transitions].map(function(e){return e.getHooks(t)}).filter(i.assertPredicate(o.isArray,"broken event named: "+t)).reduce(i.unnestR,[]).filter(function(t){return t.matches(e)})},t}();e.HookBuilder=s},function(t,e,n){"use strict";function r(t,e){function n(t){for(var e=r,n=0;n1?r:r[0]:i.isString(t)&&i.isFunction(e)?(n[t]=r,n[t].push(e),function(){return n[t].splice(n[t].indexOf(e,1))&&null}):void 0},t.prototype.build=function(t){var e=this,n=e.matcher,i=e.builders,o=this.parentName(t);if(o&&!n.find(o))return null;for(var a in i)if(i.hasOwnProperty(a)){var s=i[a].reduce(function(t,e){return function(n){return e(n,t)}},r.noop);t[a]=s(t)}return t},t.prototype.parentName=function(t){var e=t.name||"";return-1!==e.indexOf(".")?e.substring(0,e.lastIndexOf(".")):t.parent?i.isString(t.parent)?t.parent:t.parent.name:""},t.prototype.name=function(t){var e=t.name;if(-1!==e.indexOf(".")||!t.parent)return e;var n=i.isString(t.parent)?t.parent:t.parent.name;return n?n+"."+e:e},t}();e.StateBuilder=u},function(t,e,n){"use strict";function r(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}r(n(21)),r(n(24)),r(n(25)),r(n(23))},function(t,e,n){"use strict";function r(t){return t=d(t)&&{value:t}||t,s.extend(t,{$$fn:c.isInjectable(t.value)?t.value:function(){return t.value}})}function i(t,e,n,r){if(t.type&&e&&"string"!==e.name)throw new Error("Param '"+r+"' has two type configurations.");return t.type&&e&&"string"===e.name&&h.paramTypes.type(t.type)?h.paramTypes.type(t.type):e?e:t.type?t.type instanceof p.Type?t.type:h.paramTypes.type(t.type):n===m.CONFIG?h.paramTypes.type("any"):h.paramTypes.type("string"); +}function o(t,e){var n=t.squash;if(!e||n===!1)return!1;if(!c.isDefined(n)||null==n)return f.matcherConfig.defaultSquashPolicy();if(n===!0||c.isString(n))return n;throw new Error("Invalid squash policy: '"+n+"'. Valid policies: false, true, or arbitrary string")}function a(t,e,n,r){var i,o,a=[{from:"",to:n||e?void 0:""},{from:null,to:n||e?void 0:""}];return i=c.isArray(t.replace)?t.replace:[],c.isString(r)&&i.push({from:r,to:void 0}),o=s.map(i,u.prop("from")),s.filter(a,function(t){return-1===o.indexOf(t.from)}).concat(i)}var s=n(3),u=n(5),c=n(4),l=n(6),f=n(22),p=n(23),h=n(24),v=Object.prototype.hasOwnProperty,d=function(t){return 0===["value","type","squash","array","dynamic"].filter(v.bind(t||{})).length};!function(t){t[t.PATH=0]="PATH",t[t.SEARCH=1]="SEARCH",t[t.CONFIG=2]="CONFIG"}(e.DefType||(e.DefType={}));var m=e.DefType,g=function(){function t(t,e,n,u){function c(){var e={array:u===m.SEARCH?"auto":!1},r=t.match(/\[\]$/)?{array:!0}:{};return s.extend(e,r,n).array}n=r(n),e=i(n,e,u,t);var l=c();e=l?e.$asArray(l,u===m.SEARCH):e;var f=void 0!==n.value,p=n.dynamic===!0,h=o(n,f),v=a(n,l,f,h);s.extend(this,{id:t,type:e,location:u,squash:h,replace:v,isOptional:f,dynamic:p,config:n,array:l})}return t.prototype.isDefaultValue=function(t){return this.isOptional&&this.type.equals(this.value(),t)},t.prototype.value=function(t){var e=this,n=function(){if(!l.services.$injector)throw new Error("Injectable functions cannot be called at configuration time");var t=l.services.$injector.invoke(e.config.$$fn);if(null!==t&&void 0!==t&&!e.type.is(t))throw new Error("Default value ("+t+") for parameter '"+e.id+"' is not an instance of Type ("+e.type.name+")");return t},r=function(t){var n=s.map(s.filter(e.replace,u.propEq("from",t)),u.prop("to"));return n.length?n[0]:t};return t=r(t),c.isDefined(t)?this.type.$normalize(t):n()},t.prototype.isSearch=function(){return this.location===m.SEARCH},t.prototype.validates=function(t){if((!c.isDefined(t)||null===t)&&this.isOptional)return!0;var e=this.type.$normalize(t);if(!this.type.is(e))return!1;var n=this.type.encode(e);return!(c.isString(n)&&!this.type.pattern.exec(n))},t.prototype.toString=function(){return"{Param:"+this.id+" "+this.type+" squash: '"+this.squash+"' optional: "+this.isOptional+"}"},t.fromConfig=function(e,n,r){return new t(e,n,r,m.CONFIG)},t.fromPath=function(e,n,r){return new t(e,n,r,m.PATH)},t.fromSearch=function(e,n,r){return new t(e,n,r,m.SEARCH)},t.values=function(t,e){return void 0===e&&(e={}),t.map(function(t){return[t.id,t.value(e[t.id])]}).reduce(s.applyPairs,{})},t.changed=function(t,e,n){return void 0===e&&(e={}),void 0===n&&(n={}),t.filter(function(t){return!t.type.equals(e[t.id],n[t.id])})},t.equals=function(e,n,r){return void 0===n&&(n={}),void 0===r&&(r={}),0===t.changed(e,n,r).length},t.validates=function(t,e){return void 0===e&&(e={}),t.map(function(t){return t.validates(e[t.id])}).reduce(s.allTrueR,!0)},t}();e.Param=g},function(t,e,n){"use strict";var r=n(4),i=function(){function t(){this._isCaseInsensitive=!1,this._isStrictMode=!0,this._defaultSquashPolicy=!1}return t.prototype.caseInsensitive=function(t){return this._isCaseInsensitive=r.isDefined(t)?t:this._isCaseInsensitive},t.prototype.strictMode=function(t){return this._isStrictMode=r.isDefined(t)?t:this._isStrictMode},t.prototype.defaultSquashPolicy=function(t){if(r.isDefined(t)&&t!==!0&&t!==!1&&!r.isString(t))throw new Error("Invalid squash policy: "+t+". Valid policies: false, true, arbitrary-string");return this._defaultSquashPolicy=r.isDefined(t)?t:this._defaultSquashPolicy},t}();e.MatcherConfig=i,e.matcherConfig=new i},function(t,e,n){"use strict";function r(t,e){function n(t){return o.isArray(t)?t:o.isDefined(t)?[t]:[]}function r(t){switch(t.length){case 0:return;case 1:return"auto"===e?t[0]:t;default:return t}}function a(t,e){return function(a){if(o.isArray(a)&&0===a.length)return a;var s=n(a),u=i.map(s,t);return e===!0?0===i.filter(u,function(t){return!t}).length:r(u)}}function s(t){return function(e,r){var i=n(e),o=n(r);if(i.length!==o.length)return!1;for(var a=0;a=0||(s.push(i[c]),a[i[c]]=this[i[c]]);return r.extend({},a,t)},t}();e.StateParams=i},function(t,e,n){"use strict";var r=n(5),i=n(21),o=n(10),a=n(27),s=n(28),u=n(29),c=n(30),l=n(6),f=function(){function t(t,e,n,r,i,o){this.transition=t,this.$transitions=e,this.$urlRouter=n,this.$view=r,this.$state=i,this.globals=o,this.$q=l.services.$q,this.viewHooks=new s.ViewHooks(t,r),this.enterExitHooks=new u.EnterExitHooks(t),this.resolveHooks=new c.ResolveHooks(t),this.treeChanges=t.treeChanges(),this.registerUpdateGlobalState(),this.viewHooks.registerHooks(),this.enterExitHooks.registerHooks(),this.resolveHooks.registerHooks()}return t.prototype.runTransition=function(){var t=this;return this.globals.transitionHistory.enqueue(this.transition),this.transition.run().then(function(t){return t.to()})["catch"](function(e){return t.transRejected(e)})},t.prototype.registerUpdateGlobalState=function(){this.transition.onSuccess({},this.updateUrl.bind(this),{priority:9999})},t.prototype.transRejected=function(t){var e=this,n=e.transition,s=e.$state,u=e.$q;if(t instanceof o.TransitionRejection){if(t.type===o.RejectType.IGNORED){var c=s.$current.parameters().filter(r.prop("dynamic"));return i.Param.equals(c,s.params,n.params())||this.updateUrl(),s.current}if(t.type===o.RejectType.SUPERSEDED&&t.redirected&&t.detail instanceof a.TargetState)return this._redirectMgr(n.redirect(t.detail)).runTransition();t.type===o.RejectType.ABORTED&&this.$urlRouter.update()}return this.$transitions.defaultErrorHandler()(t),u.reject(t)},t.prototype.updateUrl=function(){var t=this.transition,e=this,n=e.$urlRouter,r=e.$state,i=t.options();t.$to();i.location&&r.$current.navigable&&n.push(r.$current.navigable.url,r.params,{replace:"replace"===i.location}),n.update(!0)},t.prototype._redirectMgr=function(e){var n=this,r=n.$transitions,i=n.$urlRouter,o=n.$view,a=n.$state,s=n.globals;return new t(e,r,i,o,a,s)},t}();e.TransitionManager=f},function(t,e){"use strict";var n=function(){function t(t,e,n,r){void 0===n&&(n={}),void 0===r&&(r={}),this._identifier=t,this._definition=e,this._options=r,this._params=n||{}}return t.prototype.name=function(){return this._definition&&this._definition.name||this._identifier},t.prototype.identifier=function(){return this._identifier},t.prototype.params=function(){return this._params},t.prototype.$state=function(){return this._definition},t.prototype.state=function(){return this._definition&&this._definition.self},t.prototype.options=function(){return this._options},t.prototype.exists=function(){return!(!this._definition||!this._definition.self)},t.prototype.valid=function(){return!this.error()},t.prototype.error=function(){var t=this.options().relative;if(!this._definition&&t){var e=t.name?t.name:t;return"Could not resolve '"+this.name()+"' from state '"+e+"'"}return this._definition?this._definition.self?void 0:"State '"+this.name()+"' has an invalid definition":"No such state '"+this.name()+"'"},t}();e.TargetState=n},function(t,e,n){"use strict";var r=n(3),i=n(6),o=function(){function t(t,e){this.transition=t,this.$view=e,this.treeChanges=t.treeChanges(),this.enteringViews=t.views("entering"),this.exitingViews=t.views("exiting")}return t.prototype.loadAllEnteringViews=function(){return i.services.$q.all(this.enteringViews.map(function(t){return t.load()})).then(r.noop)},t.prototype.updateViews=function(){var t=this.$view;this.exitingViews.forEach(function(e){return t.deactivateViewConfig(e)}),this.enteringViews.forEach(function(e){return t.activateViewConfig(e)}),t.sync()},t.prototype.registerHooks=function(){this.enteringViews.length&&this.transition.onStart({},this.loadAllEnteringViews.bind(this)),(this.exitingViews.length||this.enteringViews.length)&&this.transition.onSuccess({},this.updateViews.bind(this))},t}();e.ViewHooks=o},function(t,e){"use strict";var n=function(){function t(t){this.transition=t}return t.prototype.registerHooks=function(){this.registerOnEnterHooks(),this.registerOnRetainHooks(),this.registerOnExitHooks()},t.prototype.registerOnEnterHooks=function(){var t=this;this.transition.entering().filter(function(t){return!!t.onEnter}).forEach(function(e){return t.transition.onEnter({entering:e.name},e.onEnter)})},t.prototype.registerOnRetainHooks=function(){var t=this;this.transition.retained().filter(function(t){return!!t.onRetain}).forEach(function(e){return t.transition.onRetain({retained:e.name},e.onRetain)})},t.prototype.registerOnExitHooks=function(){var t=this;this.transition.exiting().filter(function(t){return!!t.onExit}).forEach(function(e){return t.transition.onExit({exiting:e.name},e.onExit)})},t}();e.EnterExitHooks=n},function(t,e,n){"use strict";var r=n(3),i=n(5),o=n(31),a=n(5),s=n(32),u=o.ResolvePolicy[o.ResolvePolicy.LAZY],c=o.ResolvePolicy[o.ResolvePolicy.EAGER],l=function(){function t(t){this.transition=t}return t.prototype.registerHooks=function(){function t(t){return r.tail(n.to).resolveContext.resolvePath(r.extend({transition:t},{resolvePolicy:c}))}function e(t,e){var o=r.find(n.entering,i.propEq("state",t)),a=o.resolveContext,c=new s.Resolvable("$resolve$",function(){return r.map(a.getResolvables(),function(t){return t.data})}),l=r.extend({transition:e},{resolvePolicy:u});return a.resolvePathElement(o.state,l).then(function(){return c.resolveResolvable(a)}).then(function(){return a.addResolvables({$resolve$:c},o.state)})}var n=this.transition.treeChanges();t.$inject=["$transition$"],e.$inject=["$state$","$transition$"],this.transition.onStart({},t,{priority:1e3}),this.transition.onEnter({entering:a.val(!0)},e,{priority:1e3})},t}();e.ResolveHooks=l},function(t,e){"use strict";!function(t){t[t.JIT=0]="JIT",t[t.LAZY=1]="LAZY",t[t.EAGER=2]="EAGER"}(e.ResolvePolicy||(e.ResolvePolicy={}));e.ResolvePolicy},function(t,e,n){"use strict";var r=n(3),i=n(5),o=n(4),a=n(6),s=n(12),u=function(){function t(t,e,n){this.promise=void 0,r.extend(this,{name:t,resolveFn:e,deps:a.services.$injector.annotate(e,a.services.$injector.strictDi),data:n})}return t.prototype.resolveResolvable=function(t,e){var n=this;void 0===e&&(e={});var i=this,o=i.name,u=i.deps,c=i.resolveFn;s.trace.traceResolveResolvable(this,e);var l=a.services.$q.defer();this.promise=l.promise;var f=t.getResolvables(null,{omitOwnLocals:[o]}),p=r.pick(f,u),h=r.map(p,function(n){return n.get(t,e)});return a.services.$q.all(h).then(function(t){try{var e=a.services.$injector.invoke(c,null,t);l.resolve(e)}catch(r){l.reject(r)}return n.promise}).then(function(t){return n.data=t,s.trace.traceResolvableResolved(n,e),n.promise})},t.prototype.get=function(t,e){return this.promise||this.resolveResolvable(t,e)},t.prototype.toString=function(){return"Resolvable(name: "+this.name+", requires: ["+this.deps+"])"},t.makeResolvables=function(e){var n=r.filter(e,i.not(o.isInjectable)),a=Object.keys(n);if(a.length)throw new Error("Invalid resolve key/value: "+a[0]+"/"+n[a[0]]);return r.map(e,function(e,n){return new t(n,e)})},t}();e.Resolvable=u},function(t,e,n){"use strict";var r=n(3),i=n(5),o=function(){function t(t){r.extend(this,t)}return t.prototype.is=function(t){return this===t||this.self===t||this.fqn()===t},t.prototype.fqn=function(){if(!(this.parent&&this.parent instanceof this.constructor))return this.name;var t=this.parent.fqn();return t?t+"."+this.name:this.name},t.prototype.root=function(){return this.parent&&this.parent.root()||this},t.prototype.parameters=function(t){t=r.defaults(t,{inherit:!0});var e=t.inherit&&this.parent&&this.parent.parameters()||[];return e.concat(r.values(this.params))},t.prototype.parameter=function(t,e){return void 0===e&&(e={}),this.url&&this.url.parameter(t,e)||r.find(r.values(this.params),i.propEq("id",t))||e.inherit&&this.parent&&this.parent.parameter(t)},t.prototype.toString=function(){return this.fqn()},t}();e.State=o},function(t,e,n){"use strict";var r=n(4),i=function(){function t(t){this._states=t}return t.prototype.isRelative=function(t){return t=t||"",0===t.indexOf(".")||0===t.indexOf("^")},t.prototype.find=function(t,e){if(t||""===t){var n=r.isString(t),i=n?t:t.name;this.isRelative(i)&&(i=this.resolvePath(i,e));var o=this._states[i];return!o||!n&&(n||o!==t&&o.self!==t)?void 0:o}},t.prototype.resolvePath=function(t,e){if(!e)throw new Error("No reference point given for path '"+t+"'");for(var n=this.find(e),r=t.split("."),i=0,o=r.length,a=n;o>i;i++)if(""!==r[i]||0!==i){if("^"!==r[i])break;if(!a.parent)throw new Error("Path '"+t+"' not valid for state '"+n.name+"'");a=a.parent}else a=n;var s=r.slice(i).join(".");return a.name+(a.name&&s?".":"")+s},t}();e.StateMatcher=i},function(t,e,n){"use strict";var r=n(3),i=n(4),o=n(17),a=function(){function t(t,e,n){this.states=t,this.builder=e,this.$urlRouterProvider=n,this.queue=[]}return t.prototype.register=function(t){var e=this,n=e.states,a=e.queue,s=e.$state,u=r.inherit(new o.State,r.extend({},t,{self:t,resolve:t.resolve||{},toString:function(){return t.name}}));if(!i.isString(u.name))throw new Error("State must have a valid name");if(n.hasOwnProperty(u.name)||-1!==r.pluck(a,"name").indexOf(u.name))throw new Error("State '"+u.name+"' is already defined");return a.push(u),this.$state&&this.flush(s),u},t.prototype.flush=function(t){for(var e,n,r,i=this,o=i.queue,a=i.states,s=i.builder,u=[],c={};o.length>0;)if(n=o.shift(),e=s.build(n),r=u.indexOf(n),e){if(a.hasOwnProperty(n.name))throw new Error("State '"+name+"' is already defined");a[n.name]=n,this.attachRoute(t,n),r>=0&&u.splice(r,1)}else{var l=c[n.name];if(c[n.name]=o.length,r>=0&&l===o.length)throw new Error("Cannot register orphaned state '"+n.name+"'");0>r&&u.push(n),o.push(n)}return a},t.prototype.autoFlush=function(t){this.$state=t,this.flush(t)},t.prototype.attachRoute=function(t,e){var n=this.$urlRouterProvider;!e[r.abstractKey]&&e.url&&n.when(e.url,["$match","$stateParams",function(n,i){t.$current.navigable===e&&r.equalForKeys(n,i)||t.transitionTo(e,n,{inherit:!0})}])},t}();e.StateQueueManager=a},function(t,e,n){"use strict";var r=n(34),i=n(19),o=n(35),a=function(){function t(t,e){this.states={},this.matcher=new r.StateMatcher(this.states),this.builder=new i.StateBuilder(this.matcher,t),this.stateQueue=new o.StateQueueManager(this.states,this.builder,e);var n={name:"",url:"^",views:null,params:{"#":{value:null,type:"hash"}},"abstract":!0},a=this._root=this.stateQueue.register(n);a.navigable=null}return t.prototype.root=function(){return this._root},t.prototype.register=function(t){return this.stateQueue.register(t)},t.prototype.get=function(t,e){var n=this;if(0===arguments.length)return Object.keys(this.states).map(function(t){return n.states[t].self});var r=this.matcher.find(t,e);return r&&r.self||null},t.prototype.decorator=function(t,e){return this.builder.builder(t,e)},t}();e.StateRegistry=a},function(t,e,n){"use strict";var r=n(3),i=n(4),o=n(8),a=n(6),s=n(38),u=n(39),c=n(43),l=n(10),f=n(27),p=n(26),h=n(21),v=n(7),d=n(3),m=n(3),g=function(){function t(e,n,r,i,o,a){this.$view=e,this.$urlRouter=n,this.$transitions=r,this.stateRegistry=i,this.stateProvider=o,this.globals=a,this.rejectFactory=new l.RejectFactory;var s=["current","$current","params","transition"],u=Object.keys(t.prototype).filter(function(t){return-1===s.indexOf(t)});m.bindFunctions(t.prototype,this,this,u)}return Object.defineProperty(t.prototype,"transition",{get:function(){return this.globals.transition},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"params",{get:function(){return this.globals.params},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"current",{get:function(){return this.globals.current},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"$current",{get:function(){return this.globals.$current},enumerable:!0,configurable:!0}),t.prototype._handleInvalidTargetState=function(t,e){function n(){var t=l.dequeue();return void 0===t?p.invalid(e.error()):d(t).then(m).then(function(t){return t||n()})}var r=this,i=function(){return r.globals.transitionHistory.peekTail()},u=i(),c=s.PathFactory.makeTargetState(t),l=new o.Queue([].concat(this.stateProvider.invalidCallbacks)),p=this.rejectFactory,h=a.services.$q,v=a.services.$injector,d=function(t){return h.when(v.invoke(t,null,{$to$:e,$from$:c}))},m=function(t){if(t instanceof f.TargetState){var e=t;return e=r.target(e.identifier(),e.params(),e.options()),e.valid()?i()!==u?p.superseded():r.transitionTo(e.identifier(),e.params(),e.options()):p.invalid(e.error())}};return n()},t.prototype.reload=function(t){return this.transitionTo(this.current,this.params,{reload:i.isDefined(t)?t:!0,inherit:!1,notify:!1})},t.prototype.go=function(t,e,n){var i={relative:this.$current,inherit:!0},o=r.defaults(n,i,c.defaultTransOpts);return this.transitionTo(t,e,o)},t.prototype.target=function(t,e,n){if(void 0===n&&(n={}),i.isObject(n.reload)&&!n.reload.name)throw new Error("Invalid reload state object");if(n.reloadState=n.reload===!0?this.stateRegistry.root():this.stateRegistry.matcher.find(n.reload,n.relative),n.reload&&!n.reloadState)throw new Error("No such reload state '"+(i.isString(n.reload)?n.reload:n.reload.name)+"'");var r=this.stateRegistry.matcher.find(t,n.relative);return new f.TargetState(t,r,e,n)},t.prototype.transitionTo=function(t,e,n){var i=this;void 0===e&&(e={}),void 0===n&&(n={});var o=this.globals.transitionHistory;n=r.defaults(n,c.defaultTransOpts),n=r.extend(n,{current:o.peekTail.bind(o)});var l=this.target(t,e,n),f=this.globals.successfulTransitions.peekTail(),h=function(){return s.PathFactory.bindTransNodesToPath([new u.Node(i.stateRegistry.root())])},v=f?f.treeChanges().to:h();if(!l.exists())return this._handleInvalidTargetState(v,l);if(!l.valid())return a.services.$q.reject(l.error());var d=this.$transitions.create(v,l),m=new p.TransitionManager(d,this.$transitions,this.$urlRouter,this.$view,this,this.globals),g=m.runTransition();return r.extend(g,{transition:d})},t.prototype.is=function(t,e,n){n=r.defaults(n,{relative:this.$current});var o=this.stateRegistry.matcher.find(t,n.relative);if(i.isDefined(o))return this.$current!==o?!1:i.isDefined(e)&&null!==e?h.Param.equals(o.parameters(),this.params,e):!0},t.prototype.includes=function(t,e,n){n=r.defaults(n,{relative:this.$current});var o=i.isString(t)&&v.Glob.fromString(t);if(o){if(!o.matches(this.$current.name))return!1;t=this.$current.name}var a=this.stateRegistry.matcher.find(t,n.relative),s=this.$current.includes;if(i.isDefined(a))return i.isDefined(s[a.name])?e?d.equalForKeys(h.Param.values(a.parameters(),e),this.params,Object.keys(e)):!0:!1},t.prototype.href=function(t,e,n){var o={lossy:!0,inherit:!0,absolute:!1,relative:this.$current};n=r.defaults(n,o);var a=this.stateRegistry.matcher.find(t,n.relative);if(!i.isDefined(a))return null;n.inherit&&(e=this.params.$inherit(e||{},this.$current,a));var s=a&&n.lossy?a.navigable:a;return s&&void 0!==s.url&&null!==s.url?this.$urlRouter.href(s.url,h.Param.values(a.parameters(),e),{absolute:n.absolute}):null},t.prototype.get=function(t,e){return 0===arguments.length?this.stateRegistry.get():this.stateRegistry.get(t,e||this.$current)},t}();e.StateService=g},function(t,e,n){"use strict";var r=n(3),i=n(5),o=n(17),a=n(39),s=n(40),u=function(){function t(){}return t.makeTargetState=function(t){var e=r.tail(t).state;return new o.TargetState(e,e,t.map(i.prop("paramValues")).reduce(r.mergeR,{}))},t.buildPath=function(t){var e=t.params();return t.$state().path.map(function(t){return new a.Node(t).applyRawParams(e)})},t.buildToPath=function(e,n){var r=t.buildPath(n);return n.options().inherit?t.inheritParams(e,r,Object.keys(n.params())):r},t.applyViewConfigs=function(t,e){return e.map(function(e){return r.extend(e,{views:r.values(e.state.views||{}).map(function(n){return t.createViewConfig(e,n)})})})},t.inheritParams=function(t,e,n){function o(t,e){var n=r.find(t,i.propEq("state",e));return r.extend({},n&&n.paramValues)}void 0===n&&(n=[]);var s=i.curry(function(t,e,n){var i=r.extend({},n&&n.paramValues),s=r.pick(i,e);i=r.omit(i,e);var u=o(t,n.state)||{},c=r.extend(i,u,s);return new a.Node(n.state).applyRawParams(c)});return e.map(s(t,n))},t.bindTransNodesToPath=function(t){var e=new s.ResolveContext(t);return t.forEach(function(t){t.resolveContext=e.isolateRootTo(t.state),t.resolveInjector=new s.ResolveInjector(t.resolveContext,t.state),t.resolves.$stateParams=new s.Resolvable("$stateParams",function(){return t.paramValues},t.paramValues)}),t},t.treeChanges=function(e,n,r){function o(t,e){var r=a.Node.clone(t);return r.paramValues=n[e].paramValues,r}for(var s=0,u=Math.min(e.length,n.length),c=function(t){return t.parameters({inherit:!1}).filter(i.not(i.prop("dynamic"))).map(i.prop("id"))},l=function(t,e){return t.equals(e,c(t.state))};u>s&&e[s].state!==r&&l(e[s],n[s]);)s++;var f,p,h,v,d,m,g,y;return f=e,p=f.slice(0,s),h=f.slice(s),m=p.map(o),g=n.slice(s),y=m.concat(g),d=t.bindTransNodesToPath(y),v=d.slice(s),{from:f,to:d,retained:p,exiting:h,entering:v}},t.bindTransitionResolve=function(t,e){var n=t.to[0];n.resolves.$transition$=new s.Resolvable("$transition$",function(){return e},e)},t.subPath=function(t,e){var n=r.find(t,function(t){return t.state===e}),i=t.indexOf(n);if(-1===i)throw new Error("The path does not contain the state: "+e);return t.slice(0,i+1)},t.paramValues=function(t){return t.reduce(function(t,e){return r.extend(t,e.paramValues)},{})},t}();e.PathFactory=u},function(t,e,n){"use strict";var r=n(3),i=n(5),o=n(40),a=function(){function t(e){if(e instanceof t){var n=e;this.state=n.state,this.paramSchema=n.paramSchema.slice(),this.paramValues=r.extend({},n.paramValues),this.resolves=r.extend({},n.resolves),this.views=n.views&&n.views.slice(),this.resolveContext=n.resolveContext,this.resolveInjector=n.resolveInjector}else this.state=e,this.paramSchema=e.parameters({inherit:!1}),this.paramValues={},this.resolves=r.mapObj(e.resolve,function(t,e){return new o.Resolvable(e,t)})}return t.prototype.applyRawParams=function(t){var e=function(e){return[e.id,e.value(t[e.id])]};return this.paramValues=this.paramSchema.reduce(function(t,n){return r.applyPairs(t,e(n))},{}),this},t.prototype.parameter=function(t){return r.find(this.paramSchema,i.propEq("id",t))},t.prototype.equals=function(t,e){var n=this;void 0===e&&(e=this.paramSchema.map(i.prop("id")));var o=function(e){return n.parameter(e).type.equals(n.paramValues[e],t.paramValues[e])};return this.state===t.state&&e.map(o).reduce(r.allTrueR,!0)},t.clone=function(e){return new t(e)},t.matching=function(t,e){var n=t.reduce(function(t,n,r){return t===r&&r=a},h=i.filter(l,f),v=function(r){return r.get(n.isolateRootTo(t),e)},d=i.map(h,v);return s.trace.traceResolvePathElement(this,h,e),u.services.$q.all(d)},t.prototype.invokeLater=function(t,e,n){var r=this;void 0===e&&(e={}),void 0===n&&(n={});var o=this.getResolvablesForFn(t);s.trace.tracePathElementInvoke(i.tail(this._path),t,Object.keys(o),i.extend({when:"Later"},n));var a=function(t){return t.get(r,n)},c=i.map(o,a);return u.services.$q.all(c).then(function(){try{return r.invokeNow(t,e,n)}catch(i){return u.services.$q.reject(i)}})},t.prototype.invokeNow=function(t,e,n){void 0===n&&(n={});var r=this.getResolvablesForFn(t);s.trace.tracePathElementInvoke(i.tail(this._path),t,Object.keys(r),i.extend({when:"Now "},n));var a=i.map(r,o.prop("data"));return u.services.$injector.invoke(t,n.bind||null,i.extend({},e,a))},t}();e.ResolveContext=h},function(t,e,n){"use strict";var r=n(3),i=function(){function t(t,e){this._resolveContext=t,this._state=e}return t.prototype.invokeLater=function(t,e){return this._resolveContext.invokeLater(t,e)},t.prototype.invokeNow=function(t,e){return this._resolveContext.invokeNow(null,t,e)},t.prototype.getLocals=function(t){var e=this,n=function(t){return t.get(e._resolveContext)};return r.map(this._resolveContext.getResolvablesForFn(t),n)},t}();e.ResolveInjector=i},function(t,e,n){"use strict";var r=n(11),i=n(15);e.defaultTransOpts={location:!0,relative:null,inherit:!1,notify:!0,reload:!1,custom:{},current:function(){return null}};var o=function(){function t(t){this.$view=t,this._defaultErrorHandler=function(t){t instanceof Error&&console.error(t)},i.HookRegistry.mixin(new i.HookRegistry,this)}return t.prototype.defaultErrorHandler=function(t){return this._defaultErrorHandler=t||this._defaultErrorHandler},t.prototype.create=function(t,e){return new r.Transition(t,e,this)},t}();e.TransitionService=o},function(t,e,n){"use strict";function r(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}r(n(39)),r(n(38))},function(t,e,n){"use strict";function r(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}r(n(46)),r(n(22)),r(n(47)),r(n(48))},function(t,e,n){"use strict";function r(t,e){var n=["",""],r=t.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!e)return r;switch(e.squash){case!1:n=["(",")"+(e.isOptional?"?":"")];break;case!0:r=r.replace(/\/$/,""),n=["(?:/(",")|/)?"];break;default:n=["("+e.squash+"|",")?"]}return r+n[0]+e.type.pattern.source+n[1]}var i=n(3),o=n(5),a=n(4),s=n(20),u=n(4),c=n(21),l=n(3),f=n(3),p=function(t,e,n){return t[e]=t[e]||n()},h=function(){function t(e,n){var a=this;this.pattern=e,this.config=n,this._cache={path:[],pattern:null},this._children=[],this._params=[],this._segments=[],this._compiled=[],this.config=i.defaults(this.config,{params:{},strict:!0,caseInsensitive:!1,paramMap:i.identity});for(var u,c,l,f=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,p=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,h=0,v=[],d=function(n){if(!t.nameValidator.test(n))throw new Error("Invalid parameter name '"+n+"' in pattern '"+e+"'");if(i.find(a._params,o.propEq("id",n)))throw new Error("Duplicate parameter name '"+n+"' in pattern '"+e+"'")},m=function(t,n){var r=t[2]||t[3],o=n?t[4]:t[4]||("*"===t[1]?".*":null);return{id:r,regexp:o,cfg:a.config.params[r],segment:e.substring(h,t.index),type:o?s.paramTypes.type(o||"string")||i.inherit(s.paramTypes.type("string"),{pattern:new RegExp(o,a.config.caseInsensitive?"i":void 0)}):null}};(u=f.exec(e))&&(c=m(u,!1),!(c.segment.indexOf("?")>=0));)d(c.id),this._params.push(s.Param.fromPath(c.id,c.type,this.config.paramMap(c.cfg,!1))),this._segments.push(c.segment),v.push([c.segment,i.tail(this._params)]),h=f.lastIndex;l=e.substring(h);var g=l.indexOf("?");if(g>=0){var y=l.substring(g);if(l=l.substring(0,g),y.length>0)for(h=0;u=p.exec(y);)c=m(u,!0),d(c.id),this._params.push(s.Param.fromSearch(c.id,c.type,this.config.paramMap(c.cfg,!0))),h=f.lastIndex}this._segments.push(l),i.extend(this,{_compiled:v.map(function(t){return r.apply(null,t)}).concat(r(l)),prefix:this._segments[0]}),Object.freeze(this)}return t.prototype.append=function(t){return this._children.push(t),i.forEach(t._cache,function(e,n){return t._cache[n]=a.isArray(e)?[]:null}),t._cache.path=this._cache.path.concat(this),t},t.prototype.isRoot=function(){return 0===this._cache.path.length},t.prototype.toString=function(){return this.pattern},t.prototype.exec=function(t,e,n,r){function a(t){ +var e=function(t){return t.split("").reverse().join("")},n=function(t){return t.replace(/\\-/g,"-")},r=e(t).split(/-(?!\\)/),o=i.map(r,e);return i.map(o,n).reverse()}var s=this;void 0===e&&(e={}),void 0===r&&(r={});var c=p(this._cache,"pattern",function(){return new RegExp(["^",i.unnest(s._cache.path.concat(s).map(o.prop("_compiled"))).join(""),s.config.strict===!1?"/?":"","$"].join(""),s.config.caseInsensitive?"i":void 0)}).exec(t);if(!c)return null;var l=this.parameters(),f=l.filter(function(t){return!t.isSearch()}),h=l.filter(function(t){return t.isSearch()}),v=this._cache.path.concat(this).map(function(t){return t._segments.length-1}).reduce(function(t,e){return t+e}),d={};if(v!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.pattern+"'");for(var m=0;v>m;m++){for(var g=f[m],y=c[m+1],w=0;wi;i++)if(r(t[i]))return;e&&r(e)}}var u=n(3),c=n(4),l=n(6),f=l.services.location,p=function(){function t(t,e){this.$urlMatcherFactory=t,this.$stateParams=e,this.rules=[],this.otherwiseFn=null,this.interceptDeferred=!1}return t.prototype.rule=function(t){if(!c.isFunction(t))throw new Error("'rule' must be a function");return this.rules.push(t),this},t.prototype.otherwise=function(t){if(!c.isFunction(t)&&!c.isString(t))throw new Error("'rule' must be a string or function");return this.otherwiseFn=c.isString(t)?function(){return t}:t,this},t.prototype.when=function(t,e){var n,a=this,s=a.$urlMatcherFactory,p=a.$stateParams,h=c.isString(e);if(c.isString(t)&&(t=s.compile(t)),!h&&!c.isFunction(e)&&!c.isArray(e))throw new Error("invalid 'handler' in when()");var v={matcher:function(t,e){return h&&(n=s.compile(e),e=["$match",n.format.bind(n)]),u.extend(function(){return o(l.services.$injector,p,e,t.exec(f.path(),f.search(),f.hash()))},{prefix:c.isString(t.prefix)?t.prefix:""})},regex:function(t,e){if(t.global||t.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(n=e,e=["$match",function(t){return i(n,t)}]),u.extend(function(){return o(l.services.$injector,p,e,t.exec(f.path()))},{prefix:r(t)})}},d={matcher:s.isMatcher(t),regex:t instanceof RegExp};for(var m in d)if(d[m])return this.rule(v[m](t,e));throw new Error("invalid 'what' in when()")},t.prototype.deferIntercept=function(t){void 0===t&&(t=!0),this.interceptDeferred=t},t}();e.UrlRouterProvider=p;var h=function(){function t(e){this.urlRouterProvider=e,u.bindFunctions(t.prototype,this,this)}return t.prototype.sync=function(){s(this.urlRouterProvider.rules,this.urlRouterProvider.otherwiseFn)},t.prototype.listen=function(){var t=this;return this.listener=this.listener||f.onChange(function(e){return s(t.urlRouterProvider.rules,t.urlRouterProvider.otherwiseFn,e)})},t.prototype.update=function(t){return t?void(this.location=f.url()):void(f.url()!==this.location&&(f.url(this.location),f.replace()))},t.prototype.push=function(t,e,n){f.url(t.format(e||{})),n&&n.replace&&f.replace()},t.prototype.href=function(t,e,n){if(!t.validates(e))return null;var r=t.format(e);n=n||{};var i=l.services.locationConfig,o=i.html5Mode();if(o||null===r||(r="#"+i.hashPrefix()+r),r=a(r,o,n.absolute),!n.absolute||!r)return r;var s=!o&&r?"/":"",u=i.port();return u=80===u||443===u?"":":"+u,[i.protocol(),"://",i.host(),u,s,r].join("")},t}();e.UrlRouter=h},function(t,e,n){"use strict";function r(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}r(n(50))},function(t,e,n){"use strict";var r=n(3),i=n(5),o=n(4),a=n(2),s=function(){function t(){var t=this;this.uiViews=[],this.viewConfigs=[],this._viewConfigFactories={},this.sync=function(){function e(t){return t.fqn.split(".").length}function n(t){for(var e=t.viewDecl.$context,n=0;++n&&e.parent;)e=e.parent;return n}var o=t.uiViews.map(function(t){return[t.fqn,t]}).reduce(r.applyPairs,{}),a=function(t){return function(e){var n=e.viewDecl,i=n.$uiViewName.split("."),a=t.fqn.split(".");if(!r.equals(i,a.slice(0-i.length)))return!1;var s=1-i.length||void 0,u=a.slice(0,s).join("."),c=o[u].creationContext;return n.$uiViewContextAnchor===(c&&c.name)}},s=i.curry(function(t,e,n,r){return e*(t(n)-t(r))}),u=function(e){var r=t.viewConfigs.filter(a(e));return r.length>1&&r.sort(s(n,-1)),[e,r[0]]},c=function(e){var n=e[0],r=e[1];-1!==t.uiViews.indexOf(n)&&n.configUpdated(r)};t.uiViews.sort(s(e,1)).map(u).forEach(c)}}return t.prototype.rootContext=function(t){return this._rootContext=t||this._rootContext},t.prototype.viewConfigFactory=function(t,e){this._viewConfigFactories[t]=e},t.prototype.createViewConfig=function(t,e){var n=this._viewConfigFactories[e.$type];if(!n)throw new Error("ViewService: No view config factory registered for type "+e.$type);return n(t,e)},t.prototype.deactivateViewConfig=function(t){a.trace.traceViewServiceEvent("<- Removing",t),r.removeFrom(this.viewConfigs,t)},t.prototype.activateViewConfig=function(t){a.trace.traceViewServiceEvent("-> Registering",t),this.viewConfigs.push(t)},t.prototype.registerUiView=function(t){a.trace.traceViewServiceUiViewEvent("-> Registering",t);var e=this.uiViews,n=function(e){return e.fqn===t.fqn};return e.filter(n).length&&a.trace.traceViewServiceUiViewEvent("!!!! duplicate uiView named:",t),e.push(t),this.sync(),function(){var n=e.indexOf(t);return 0>=n?void a.trace.traceViewServiceUiViewEvent("Tried removing non-registered uiView",t):(a.trace.traceViewServiceUiViewEvent("<- Deregistering",t),void r.removeFrom(e)(t))}},t.prototype.available=function(){return this.uiViews.map(i.prop("fqn"))},t.prototype.active=function(){return this.uiViews.filter(i.prop("$config")).map(i.prop("name"))},t.normalizeUiViewTarget=function(t,e){void 0===e&&(e="");var n=e.split("@"),r=n[0]||"$default",i=o.isString(n[1])?n[1]:"^",a=/^(\^(?:\.\^)*)\.(.*$)/.exec(r);a&&(i=a[1],r=a[2]),"!"===r.charAt(0)&&(r=r.substr(1),i="");var s=/^(\^(?:\.\^)*)$/;if(s.exec(i)){var u=i.split(".").reduce(function(t,e){return t.parent},t);i=u.name}return{uiViewName:r,uiViewContextAnchor:i}},t}();e.ViewService=s},function(t,e,n){"use strict";var r=n(25),i=n(8),o=n(3),a=function(){function t(t){var e=this;this.params=new r.StateParams,this.transitionHistory=new i.Queue([],1),this.successfulTransitions=new i.Queue([],1);var n=function(t){e.transition=t,e.transitionHistory.enqueue(t);var n=function(){e.successfulTransitions.enqueue(t),e.$current=t.$to(),e.current=e.$current.self,o.copy(t.params(),e.params)};t.onSuccess({},n,{priority:1e4});var r=function(){e.transition===t&&(e.transition=null)};t.promise.then(r,r)};t.onBefore({},["$transition$",n])}return t}();e.UIRouterGlobals=a},function(t,e,n){"use strict";var r=n(47),i=n(48),o=n(18),a=n(48),s=n(43),u=n(50),c=n(36),l=n(37),f=n(51),p=function(){function t(){this.viewService=new u.ViewService,this.transitionService=new s.TransitionService(this.viewService),this.globals=new f.UIRouterGlobals(this.transitionService),this.urlMatcherFactory=new r.UrlMatcherFactory,this.urlRouterProvider=new i.UrlRouterProvider(this.urlMatcherFactory,this.globals.params),this.urlRouter=new a.UrlRouter(this.urlRouterProvider),this.stateRegistry=new c.StateRegistry(this.urlMatcherFactory,this.urlRouterProvider),this.stateProvider=new o.StateProvider(this.stateRegistry),this.stateService=new l.StateService(this.viewService,this.urlRouter,this.transitionService,this.stateRegistry,this.stateProvider,this.globals),this.viewService.rootContext(this.stateRegistry.root()),this.globals.$current=this.stateRegistry.root(),this.globals.current=this.globals.$current.self}return t}();e.UIRouter=p},function(t,e,n){"use strict";function r(t){var e=f.services.$injector,n=e.get("$controller"),r=e.instantiate;try{var i;return e.instantiate=function(t){e.instantiate=r,i=e.annotate(t)},n(t,{$scope:{}}),i}finally{e.instantiate=r}}function i(t,e){f.services.$injector=t,f.services.$q=e}function o(t){function e(e,r,i,o,a,s){return o.$on("$locationChangeSuccess",function(t){return n.forEach(function(e){return e(t)})}),f.services.locationConfig.html5Mode=function(){var e=t.html5Mode();return e=v.isObject(e)?e.enabled:e,e&&i.history},f.services.template.get=function(t){return a.get(t,{cache:s,headers:{Accept:"text/html"}}).then(h.prop("data"))},p.bindFunctions(e,f.services.location,e,["replace","url","path","search","hash"]),p.bindFunctions(e,f.services.locationConfig,e,["port","protocol","host"]),p.bindFunctions(r,f.services.locationConfig,r,["baseHref"]),S}S=new l.UIRouter,S.stateRegistry.decorator("views",w.ng1ViewsBuilder),S.viewService.viewConfigFactory("ng1",w.ng1ViewConfigFactory),p.bindFunctions(t,f.services.locationConfig,t,["hashPrefix"]);var n=[];f.services.location.onChange=function(t){return n.push(t),function(){return p.removeFrom(n)(t)}},this.$get=e,e.$inject=["$location","$browser","$sniffer","$rootScope","$http","$templateCache"]}function a(){return S.urlRouterProvider.$get=function(){return S.urlRouter.update(!0),this.interceptDeferred||S.urlRouter.listen(),S.urlRouter},S.urlRouterProvider}function s(){return S.stateProvider.$get=function(){return S.stateRegistry.stateQueue.autoFlush(S.stateService),S.stateService},S.stateProvider}function u(){function t(t){var e=function(e){function n(){}var i=p.find(t.treeChanges().to,h.propEq("state",e.viewDecl.$context));if(!i)return f.services.$q.when();var o=i.resolveContext,a=r(e.controller),s=o.getResolvables();return n.$inject=a.filter(function(t){return s.hasOwnProperty(t)}),o.invokeLater(n).then(function(){return e.locals=p.map(s,function(t){return t.data})})},n=t.views("entering").filter(function(t){return!!t.controller}).map(e);return f.services.$q.all(n).then(p.noop)}return t.$inject=["$transition$"],S.transitionService.onFinish({},t),S.transitionService.$get=function(){return S.transitionService},S.transitionService}function c(t){t.$watch(function(){y.trace.approximateDigests++})}var l=n(52),f=n(6),p=n(3),h=n(5),v=n(4),d=n(44),m=n(40),g=n(17),y=n(12),w=n(54),$=n(55),b=angular.module("ui.router.angular1",[]);angular.module("ui.router.util",["ng","ui.router.init"]),angular.module("ui.router.router",["ui.router.util"]),angular.module("ui.router.state",["ui.router.router","ui.router.util","ui.router.angular1"]),angular.module("ui.router",["ui.router.init","ui.router.state","ui.router.angular1"]),angular.module("ui.router.compat",["ui.router"]),e.annotateController=r,i.$inject=["$injector","$q"],b.run(i);var S=null;o.$inject=["$locationProvider"];var R=function(){return{resolve:function(t,e,n){void 0===e&&(e={});var r=new d.Node(new g.State({params:{}})),i=new d.Node(new g.State({params:{}})),o=new m.ResolveContext([r,i]);o.addResolvables(m.Resolvable.makeResolvables(t),i.state);var a=function(t){var n=function(t){return m.Resolvable.makeResolvables(p.map(t,function(t){return function(){return t}}))};return o.addResolvables(n(t),r.state),o.addResolvables(n(e),i.state),o.resolvePath()};return n?n.then(a):a({})}}};angular.module("ui.router.init",[]).provider("ng1UIRouter",o),angular.module("ui.router.init").run(["ng1UIRouter",function(t){}]),angular.module("ui.router.util").provider("$urlMatcherFactory",["ng1UIRouterProvider",function(){return S.urlMatcherFactory}]),angular.module("ui.router.util").run(["$urlMatcherFactory",function(t){}]),angular.module("ui.router.router").provider("$urlRouter",["ng1UIRouterProvider",a]),angular.module("ui.router.router").run(["$urlRouter",function(t){}]),angular.module("ui.router.state").provider("$state",["ng1UIRouterProvider",s]),angular.module("ui.router.state").run(["$state",function(t){}]),angular.module("ui.router.state").factory("$stateParams",["ng1UIRouter",function(t){return t.globals.params}]),angular.module("ui.router.state").provider("$transitions",["ng1UIRouterProvider",u]),angular.module("ui.router.util").factory("$templateFactory",["ng1UIRouter",function(){return new $.TemplateFactory}]),angular.module("ui.router").factory("$view",function(){return S.viewService}),angular.module("ui.router").factory("$resolve",R),angular.module("ui.router").service("$trace",function(){return y.trace}),c.$inject=["$rootScope"],e.watchDigests=c,angular.module("ui.router").run(c)},function(t,e,n){"use strict";function r(t){var e=["templateProvider","templateUrl","template","notify","async"],n=["controller","controllerProvider","controllerAs","resolveAs"],r=["component","bindings"],c=e.concat(n),l=r.concat(c),f={},p=t.views||{$default:o.pick(t,l)};return o.forEach(p,function(e,n){if(n=n||"$default",u.isString(e)&&(e={component:e}),Object.keys(e).length){if(e.component){if(c.map(function(t){return u.isDefined(e[t])}).reduce(o.anyTrueR,!1))throw new Error("Cannot combine: "+r.join("|")+" with: "+c.join("|")+" in stateview: 'name@"+t.name+"'");e.templateProvider=["$injector",function(t){var n=function(t){return e.bindings&&e.bindings[t]||t},r=angular.version.minor>=3?"::":"",o=i(t,e.component).map(function(t){return a.kebobString(t)+"='"+r+"$resolve."+n(t)+"'"}).join(" "),s=a.kebobString(e.component);return"<"+s+" "+o+">"}]}e.resolveAs=e.resolveAs||"$resolve",e.$type="ng1",e.$context=t,e.$name=n;var l=s.ViewService.normalizeUiViewTarget(e.$context,e.$name);e.$uiViewName=l.uiViewName,e.$uiViewContextAnchor=l.uiViewContextAnchor,f[n]=e}}),f}function i(t,e){var n=t.get(e+"Directive");if(!n||!n.length)throw new Error("Unable to find component named '"+e+"'");return n.map(v).reduce(o.unnestR,[])}var o=n(3),a=n(9),s=n(50),u=n(4),c=n(6),l=n(12),f=n(55);e.ng1ViewConfigFactory=function(t,e){return new d(t,e)},e.ng1ViewsBuilder=r;var p=function(t){return Object.keys(t||{}).map(function(e){return[e,/^[=<](.*)/.exec(t[e])]}).filter(function(t){return u.isDefined(t[1])}).map(function(t){return t[1][1]||t[0]})},h=function(t){return Object.keys(t||{}).filter(function(e){return!!/[=<]/.exec(t[e].mode)}).map(function(e){return t[e].attrName})},v=function(t){return u.isObject(t.bindToController)?p(t.bindToController):t.$$bindings&&t.$$bindings.bindToController?h(t.$$bindings.bindToController):t.$$isolateBindings?h(t.$$isolateBindings):p(t.scope)},d=function(){function t(t,e){this.node=t,this.viewDecl=e,this.loaded=!1}return t.prototype.load=function(){var t=this,e=c.services.$q;if(!this.hasTemplate())throw new Error("No template configuration specified for '"+this.viewDecl.$uiViewName+"@"+this.viewDecl.$uiViewContextAnchor+"'");var n=this.node.resolveContext,r=this.node.paramValues,i={template:e.when(this.getTemplate(r,new f.TemplateFactory,n)),controller:e.when(this.getController(n))};return e.all(i).then(function(e){l.trace.traceViewServiceEvent("Loaded",t),t.controller=e.controller,t.template=e.template})},t.prototype.hasTemplate=function(){return!!(this.viewDecl.template||this.viewDecl.templateUrl||this.viewDecl.templateProvider)},t.prototype.getTemplate=function(t,e,n){return e.fromConfig(this.viewDecl,t,n.invokeLater.bind(n))},t.prototype.getController=function(t){var e=this.viewDecl.controllerProvider;return u.isInjectable(e)?t.invokeLater(e,{}):this.viewDecl.controller},t}();e.Ng1ViewConfig=d},function(t,e,n){"use strict";var r=n(4),i=n(6),o=function(){function t(){}return t.prototype.fromConfig=function(t,e,n){return r.isDefined(t.template)?this.fromString(t.template,e):r.isDefined(t.templateUrl)?this.fromUrl(t.templateUrl,e):r.isDefined(t.templateProvider)?this.fromProvider(t.templateProvider,e,n):null},t.prototype.fromString=function(t,e){return r.isFunction(t)?t(e):t},t.prototype.fromUrl=function(t,e){return r.isFunction(t)&&(t=t(e)),null==t?null:i.services.template.get(t)},t.prototype.fromProvider=function(t,e,n){return n(t)},t}();e.TemplateFactory=o},function(t,e,n){"use strict";function r(t,e){var n,r=t.match(/^\s*({[^}]*})\s*$/);if(r&&(t=e+"("+r[1]+")"),n=t.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!n||4!==n.length)throw new Error("Invalid state ref '"+t+"'");return{state:n[1],paramExpr:n[3]||null}}function i(t){var e=t.parent().inheritedData("$uiView"),n=l.parse("$cfg.node.state")(e);return n&&n.name?n:void 0}function o(t){var e="[object SVGAnimatedString]"===Object.prototype.toString.call(t.prop("href")),n="FORM"===t[0].nodeName;return{attr:n?"action":e?"xlink:href":"href",isAnchor:"A"===t.prop("tagName").toUpperCase(),clickable:!n}}function a(t,e,n,r,i){return function(o){var a=o.which||o.button,s=i();if(!(a>1||o.ctrlKey||o.metaKey||o.shiftKey||t.attr("target"))){var u=n(function(){e.go(s.state,s.params,s.options)});o.preventDefault();var c=r.isAnchor&&!s.href?1:0;o.preventDefault=function(){c--<=0&&n.cancel(u)}}}}function s(t,e){return{relative:i(t)||e.$current,inherit:!0}}var u=n(3),c=n(4),l=n(5),f=["$state","$timeout",function(t,e){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(n,i,c,l){var f=r(c.uiSref,t.current.name),p={state:f.state,href:null,params:null,options:null},h=o(i),v=l[1]||l[0],d=null;p.options=u.extend(s(i,t),c.uiSrefOpts?n.$eval(c.uiSrefOpts):{});var m=function(e){e&&(p.params=angular.copy(e)),p.href=t.href(f.state,p.params,p.options),d&&d(),v&&(d=v.$$addStateInfo(f.state,p.params)),null!==p.href&&c.$set(h.attr,p.href)};f.paramExpr&&(n.$watch(f.paramExpr,function(t){t!==p.params&&m(t)},!0),p.params=angular.copy(n.$eval(f.paramExpr))),m(),h.clickable&&i.bind("click",a(i,t,e,h,function(){return p}))}}}],p=["$state","$timeout",function(t,e){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(n,r,i,s){function u(e){h.state=e[0],h.params=e[1],h.options=e[2],h.href=t.href(h.state,h.params,h.options),v&&v(),l&&(v=l.$$addStateInfo(h.state,h.params)),h.href&&i.$set(c.attr,h.href)}var c=o(r),l=s[1]||s[0],f=[i.uiState,i.uiStateParams||null,i.uiStateOpts||null],p="["+f.map(function(t){return t||"null"}).join(", ")+"]",h={state:null,params:null,options:null,href:null},v=null;n.$watch(p,u,!0),u(n.$eval(p)),c.clickable&&r.bind("click",a(r,t,e,c,function(){return h}))}}}],h=["$state","$stateParams","$interpolate","$transitions",function(t,e,n,o){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(e,a,s,l){function f(e,n,r){var o=t.get(e,i(a)),s=p(e,n),u={state:o||{name:e},params:n,hash:s};return $.push(u),b[s]=r,function(){var t=$.indexOf(u);-1!==t&&$.splice(t,1)}}function p(t,n){if(!c.isString(t))throw new Error("state should be a string");return c.isObject(n)?t+u.toJson(n):(n=e.$eval(n),c.isObject(n)?t+u.toJson(n):t)}function h(){for(var t=0;t<$.length;t++)m($[t].state,$[t].params)?v(a,b[$[t].hash]):d(a,b[$[t].hash]),g($[t].state,$[t].params)?v(a,y):d(a,y)}function v(t,e){l(function(){t.addClass(e)})}function d(t,e){t.removeClass(e)}function m(e,n){return t.includes(e.name,n)}function g(e,n){return t.is(e.name,n)}var y,w,$=[],b={};y=n(s.uiSrefActiveEq||"",!1)(e);try{w=e.$eval(s.uiSrefActive)}catch(S){}w=w||n(s.uiSrefActive||"",!1)(e),c.isObject(w)&&u.forEach(w,function(n,i){if(c.isString(n)){var o=r(n,t.current.name);f(o.state,e.$eval(o.paramExpr),i)}}),this.$$addStateInfo=function(t,e){if(!(c.isObject(w)&&$.length>0)){var n=f(t,e,w);return h(),n}},e.$on("$stateChangeSuccess",h);var R=["$transition$",function(t){t.promise.then(h)}],x=o.onStart({},R);e.$on("$destroy",x),h()}]}}];angular.module("ui.router.state").directive("uiSref",f).directive("uiSrefActive",h).directive("uiSrefActiveEq",h).directive("uiState",p)},function(t,e){"use strict";function n(t){var e=function(e,n,r){return t.is(e,n,r)};return e.$stateful=!0,e}function r(t){var e=function(e,n,r){return t.includes(e,n,r)};return e.$stateful=!0,e}n.$inject=["$state"],e.$IsStateFilter=n,r.$inject=["$state"],e.$IncludedByStateFilter=r,angular.module("ui.router.state").filter("isState",n).filter("includedByState",r)},function(t,e,n){"use strict";function r(t,e,n,r,u){var f=c.parse("viewDecl.controllerAs"),p=c.parse("viewDecl.resolveAs"),h=c.parse("node.resolveContext");return{restrict:"ECA",priority:-400,compile:function(r){var u=r.html();return function(r,c){var v=c.data("$uiView");if(v){var d=v.$cfg||{viewDecl:{}};c.html(d.template||u),s.trace.traceUiViewFill(v.$uiView,c.html());var m=t(c.contents()),g=d.controller,y=f(d),w=p(d),$=h(d),b=$&&o.map($.getResolvables(),function(t){return t.data});if(r[w]=b,g){var S=e(g,o.extend({},b,{$scope:r,$element:c}));y&&(r[y]=S,r[y][w]=b),c.data("$ngControllerController",S),c.children().data("$ngControllerController",S),i(n,S,r,d)}if(a.isString(d.viewDecl.component))var R=d.viewDecl.component,x=l.kebobString(R),E=function(){var t=[].slice.call(c[0].children).filter(function(t){return t&&t.tagName&&t.tagName.toLowerCase()===x});return t&&angular.element(t).data("$"+R+"Controller")},k=r.$watch(E,function(t){t&&(i(n,t,r,d),k())});m(r)}}}}}function i(t,e,n,r){!a.isFunction(e.$onInit)||r.viewDecl.component&&p||e.$onInit();var i={bind:e};if(a.isFunction(e.uiOnParamsChanged)){var s=function(t){var n=r.node.resolveContext,i=n.getResolvables().$transition$.data;if(t!==i&&-1===t.exiting().indexOf(r.node.state.self)){var a=t.params("to"),s=t.params("from"),u=t.treeChanges().to.map(function(t){return t.paramSchema}).reduce(o.unnestR,[]),c=t.treeChanges().from.map(function(t){return t.paramSchema}).reduce(o.unnestR,[]),l=u.filter(function(t){var e=c.indexOf(t);return-1===e||!c[e].type.equals(a[t.id],s[t.id])});if(l.length){var f=l.map(function(t){return t.id});e.uiOnParamsChanged(o.filter(a,function(t,e){return-1!==f.indexOf(e)}),t)}}};n.$on("$destroy",t.onSuccess({},["$transition$",s]),i);var c=function(t,e){t.type===u.RejectType.IGNORED&&s(e)};n.$on("$destroy",t.onError({},["$error$","$transition$",c]),i)}if(a.isFunction(e.uiCanExit)){var l={exiting:r.node.state.name};n.$on("$destroy",t.onBefore(l,e.uiCanExit,i))}}var o=n(3),a=n(4),s=n(12),u=n(10),c=n(5),l=n(9),f=["$view","$animate","$uiViewScroll","$interpolate","$q",function(t,e,n,r,i){function o(t,n){return{enter:function(t,n,r){angular.version.minor>2?e.enter(t,null,n).then(r):e.enter(t,null,n,r)},leave:function(t,n){angular.version.minor>2?e.leave(t).then(n):e.leave(t,n)}}}function u(t,e){return t===e}var l={$cfg:{viewDecl:{$context:t.rootContext()}},$uiView:{}},f={count:0,restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(e,p,h){return function(e,p,v){function d(t){u(E,t)||(s.trace.traceUiViewConfigUpdated(O,t&&t.viewDecl&&t.viewDecl.$context),E=t,g(t))}function m(){if(y&&(s.trace.traceUiViewEvent("Removing (previous) el",y.data("$uiView")),y.remove(),y=null),$&&(s.trace.traceUiViewEvent("Destroying scope",O),$.$destroy(),$=null),w){var t=w.data("$uiView");s.trace.traceUiViewEvent("Animate out",t),x.leave(w,function(){t.$$animLeave.resolve(),y=null}),y=w,w=null}}function g(t){var r=e.$new();s.trace.traceUiViewScopeCreated(O,r);var o=i.defer(),u=i.defer(),c={$cfg:t,$uiView:O,$animEnter:o.promise,$animLeave:u.promise,$$animLeave:u},l=h(r,function(t){x.enter(t.data("$uiView",c),p,function(){o.resolve(),$&&$.$emit("$viewContentAnimationEnded"),(a.isDefined(R)&&!R||e.$eval(R))&&n(t)}),m()});w=l,$=r,$.$emit("$viewContentLoaded",t||E),$.$eval(S)}var y,w,$,b,S=v.onload||"",R=v.autoscroll,x=o(v,e),E=void 0,k=p.inheritedData("$uiView")||l,C=r(v.uiView||v.name||"")(e)||"$default",O={id:f.count++,name:C,fqn:k.$uiView.fqn?k.$uiView.fqn+"."+C:C,config:null,configUpdated:d,get creationContext(){return c.parse("$cfg.viewDecl.$context")(k)}};s.trace.traceUiViewEvent("Linking",O),p.data("$uiView",{$uiView:O}),g(),b=t.registerUiView(O),e.$on("$destroy",function(){s.trace.traceUiViewEvent("Destroying/Unregistering",O),b()})}}};return f}];r.$inject=["$compile","$controller","$transitions","$view","$timeout"];var p="function"==typeof angular.module("ui.router").component;angular.module("ui.router.state").directive("uiView",f),angular.module("ui.router.state").directive("uiView",r)},function(t,e){"use strict";function n(){var t=!1;this.useAnchorScroll=function(){t=!0},this.$get=["$anchorScroll","$timeout",function(e,n){return t?e:function(t){return n(function(){t[0].scrollIntoView()},0,!1)}}]}angular.module("ui.router.state").provider("$uiViewScroll",n)}])}); +//# sourceMappingURL=angular-ui-router.min.js.map \ No newline at end of file