summaryrefslogtreecommitdiffstats
path: root/js/vendor/angular/angular.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/vendor/angular/angular.js')
-rw-r--r--js/vendor/angular/angular.js1320
1 files changed, 737 insertions, 583 deletions
diff --git a/js/vendor/angular/angular.js b/js/vendor/angular/angular.js
index 1f64012df..bdc97abb0 100644
--- a/js/vendor/angular/angular.js
+++ b/js/vendor/angular/angular.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.3.0-rc.0
+ * @license AngularJS v1.3.0-rc.1
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
@@ -71,7 +71,7 @@ function minErr(module, ErrorConstructor) {
return match;
});
- message = message + '\nhttp://errors.angularjs.org/1.3.0-rc.0/' +
+ message = message + '\nhttp://errors.angularjs.org/1.3.0-rc.1/' +
(module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) {
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -134,7 +134,6 @@ function minErr(module, ErrorConstructor) {
map: true,
size: true,
includes: true,
- indexOf: true,
arrayRemove: true,
isLeafNode: true,
copy: true,
@@ -292,9 +291,9 @@ function isArrayLike(obj) {
*
* @description
* Invokes the `iterator` function once for each item in `obj` collection, which can be either an
- * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
- * is the value of an object property or an array element and `key` is the object property key or
- * array element index. Specifying a `context` for the function is optional.
+ * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
+ * is the value of an object property or an array element, `key` is the object property key or
+ * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
*
* It is worth noting that `.forEach` does not iterate over inherited properties because it filters
* using the `hasOwnProperty` method.
@@ -322,22 +321,22 @@ function forEach(obj, iterator, context) {
// Need to check if hasOwnProperty exists,
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
- iterator.call(context, obj[key], key);
+ iterator.call(context, obj[key], key, obj);
}
}
} else if (isArray(obj) || isArrayLike(obj)) {
var isPrimitive = typeof obj !== 'object';
for (key = 0, length = obj.length; key < length; key++) {
if (isPrimitive || key in obj) {
- iterator.call(context, obj[key], key);
+ iterator.call(context, obj[key], key, obj);
}
}
} else if (obj.forEach && obj.forEach !== forEach) {
- obj.forEach(iterator, context);
+ obj.forEach(iterator, context, obj);
} else {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
- iterator.call(context, obj[key], key);
+ iterator.call(context, obj[key], key, obj);
}
}
}
@@ -418,15 +417,19 @@ function setHashKey(obj, h) {
*/
function extend(dst) {
var h = dst.$$hashKey;
- forEach(arguments, function(obj) {
- if (obj !== dst) {
- forEach(obj, function(value, key) {
- dst[key] = value;
- });
+
+ for (var i = 1, ii = arguments.length; i < ii; i++) {
+ var obj = arguments[i];
+ if (obj) {
+ var keys = Object.keys(obj);
+ for (var j = 0, jj = keys.length; j < jj; j++) {
+ var key = keys[j];
+ dst[key] = obj[key];
+ }
}
- });
+ }
- setHashKey(dst,h);
+ setHashKey(dst, h);
return dst;
}
@@ -732,20 +735,11 @@ function size(obj, ownPropsOnly) {
function includes(array, obj) {
- return indexOf(array, obj) != -1;
-}
-
-function indexOf(array, obj) {
- if (array.indexOf) return array.indexOf(obj);
-
- for (var i = 0; i < array.length; i++) {
- if (obj === array[i]) return i;
- }
- return -1;
+ return Array.prototype.indexOf.call(array, obj) != -1;
}
function arrayRemove(array, value) {
- var index = indexOf(array, value);
+ var index = array.indexOf(value);
if (index >=0)
array.splice(index, 1);
return value;
@@ -850,7 +844,7 @@ function copy(source, destination, stackSource, stackDest) {
stackDest = stackDest || [];
if (isObject(source)) {
- var index = indexOf(stackSource, source);
+ var index = stackSource.indexOf(source);
if (index !== -1) return stackDest[index];
stackSource.push(source);
@@ -1591,9 +1585,13 @@ function bindJQuery() {
// the $destroy event on all removed nodes.
originalCleanData = jQuery.cleanData;
jQuery.cleanData = function(elems) {
+ var events;
if (!skipDestroyOnNextJQueryCleanData) {
for (var i = 0, elem; (elem = elems[i]) != null; i++) {
- jQuery(elem).triggerHandler('$destroy');
+ events = jQuery._data(elem, "events");
+ if (events && events.$destroy) {
+ jQuery(elem).triggerHandler('$destroy');
+ }
}
} else {
skipDestroyOnNextJQueryCleanData = false;
@@ -2124,11 +2122,11 @@ function setupModuleLoader(window) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.3.0-rc.0', // all of these placeholder strings will be replaced by grunt's
+ full: '1.3.0-rc.1', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
minor: 3,
dot: 0,
- codeName: 'sonic-boltification'
+ codeName: 'backyard-atomicity'
};
@@ -2162,7 +2160,8 @@ function publishExternalAPI(angular){
'getTestability': getTestability,
'$$minErr': minErr,
'$$csp': csp,
- 'reloadWithDebugInfo': reloadWithDebugInfo
+ 'reloadWithDebugInfo': reloadWithDebugInfo,
+ '$$hasClass': jqLiteHasClass
});
angularModule = setupModuleLoader(window);
@@ -2770,6 +2769,8 @@ forEach('input,select,option,textarea,button,form,details'.split(','), function(
var ALIASED_ATTR = {
'ngMinlength' : 'minlength',
'ngMaxlength' : 'maxlength',
+ 'ngMin' : 'min',
+ 'ngMax' : 'max',
'ngPattern' : 'pattern'
};
@@ -5528,9 +5529,17 @@ function $TemplateCacheProvider() {
*
*
* #### `templateUrl`
- * Same as `template` but the template is loaded from the specified URL. Because
- * the template loading is asynchronous the compilation/linking is suspended until the template
- * is loaded.
+ * This is similar to `template` but the template is loaded from the specified URL, asynchronously.
+ *
+ * Because template loading is asynchronous the compiler will suspend compilation of directives on that element
+ * for later when the template has been resolved. In the meantime it will continue to compile and link
+ * sibling and parent elements as though this element had not contained any directives.
+ *
+ * The compiler does not suspend the entire compilation to wait for templates to be loaded because this
+ * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the
+ * case when only one deeply nested directive has `templateUrl`.
+ *
+ * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
*
* You can specify `templateUrl` as a string representing the URL or as a function which takes two
* arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
@@ -5657,7 +5666,14 @@ function $TemplateCacheProvider() {
*
* #### Post-linking function
*
- * Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.
+ * Executed after the child elements are linked.
+ *
+ * Note that child elements that contain `templateUrl` directives will not have been compiled
+ * and linked since they are waiting for their template to load asynchronously and their own
+ * compilation and linking has been suspended until that occurs.
+ *
+ * It is safe to do DOM transformation in the post-linking function on elements that are not waiting
+ * for their async templates to be resolved.
*
* <a name="Attributes"></a>
* ### Attributes
@@ -5813,7 +5829,6 @@ var $compileMinErr = minErr('$compile');
/**
* @ngdoc provider
* @name $compileProvider
- * @kind function
*
* @description
*/
@@ -7451,6 +7466,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (parent) {
parent.replaceChild(newNode, firstElementToRemove);
}
+
+ // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
var fragment = document.createDocumentFragment();
fragment.appendChild(firstElementToRemove);
@@ -8029,7 +8046,7 @@ function $HttpProvider() {
* it is important to familiarize yourself with these APIs and the guarantees they provide.
*
*
- * # General usage
+ * ## General usage
* The `$http` service is a function which takes a single argument — a configuration object —
* that is used to generate an HTTP request and returns a {@link ng.$q promise}
* with two $http specific methods: `success` and `error`.
@@ -8056,7 +8073,7 @@ function $HttpProvider() {
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
* called for such responses.
*
- * # Writing Unit Tests that use $http
+ * ## Writing Unit Tests that use $http
* When unit testing (using {@link ngMock ngMock}), it is necessary to call
* {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
* request using trained responses.
@@ -8067,7 +8084,7 @@ function $HttpProvider() {
* $httpBackend.flush();
* ```
*
- * # Shortcut methods
+ * ## Shortcut methods
*
* Shortcut methods are also available. All shortcut methods require passing in the URL, and
* request data must be passed in for POST/PUT requests.
@@ -8088,7 +8105,7 @@ function $HttpProvider() {
* - {@link ng.$http#patch $http.patch}
*
*
- * # Setting HTTP Headers
+ * ## Setting HTTP Headers
*
* The $http service will automatically add certain HTTP headers to all requests. These defaults
* can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
@@ -8119,36 +8136,69 @@ function $HttpProvider() {
* calling `$http(config)`, which overrides the defaults without changing them globally.
*
*
- * # Transforming Requests and Responses
+ * ## Transforming Requests and Responses
+ *
+ * Both requests and responses can be transformed using transformation functions: `transformRequest`
+ * and `transformResponse`. These properties can be a single function that returns
+ * the transformed value (`{function(data, headersGetter)`) or an array of such transformation functions,
+ * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
+ *
+ * ### Default Transformations
+ *
+ * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
+ * `defaults.transformResponse` properties. If a request does not provide its own transformations
+ * then these will be applied.
+ *
+ * You can augment or replace the default transformations by modifying these properties by adding to or
+ * replacing the array.
*
- * Both requests and responses can be transformed using transform functions. By default, Angular
- * applies these transformations:
+ * Angular provides the following default transformations:
*
- * Request transformations:
+ * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
*
* - If the `data` property of the request configuration object contains an object, serialize it
* into JSON format.
*
- * Response transformations:
+ * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
*
* - If XSRF prefix is detected, strip it (see Security Considerations section below).
* - If JSON response is detected, deserialize it using a JSON parser.
*
- * To globally augment or override the default transforms, modify the
- * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse`
- * properties. These properties are by default an array of transform functions, which allows you
- * to `push` or `unshift` a new transformation function into the transformation chain. You can
- * also decide to completely override any default transformations by assigning your
- * transformation functions to these properties directly without the array wrapper. These defaults
- * are again available on the $http factory at run-time, which may be useful if you have run-time
- * services you wish to be involved in your transformations.
*
- * Similarly, to locally override the request/response transforms, augment the
- * `transformRequest` and/or `transformResponse` properties of the configuration object passed
+ * ### Overriding the Default Transformations Per Request
+ *
+ * If you wish override the request/response transformations only for a single request then provide
+ * `transformRequest` and/or `transformResponse` properties on the configuration object passed
* into `$http`.
*
+ * Note that if you provide these properties on the config object the default transformations will be
+ * overwritten. If you wish to augment the default transformations then you must include them in your
+ * local transformation array.
+ *
+ * The following code demonstrates adding a new response transformation to be run after the default response
+ * transformations have been run.
+ *
+ * ```js
+ * function appendTransform(defaults, transform) {
+ *
+ * // We can't guarantee that the default transformation is an array
+ * defaults = angular.isArray(defaults) ? defaults : [defaults];
*
- * # Caching
+ * // Append the new transformation to the defaults
+ * return defaults.concat(transform);
+ * }
+ *
+ * $http({
+ * url: '...',
+ * method: 'GET',
+ * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
+ * return doTransform(value);
+ * })
+ * });
+ * ```
+ *
+ *
+ * ## Caching
*
* To enable caching, set the request configuration `cache` property to `true` (to use default
* cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
@@ -8171,7 +8221,7 @@ function $HttpProvider() {
* If you set the default cache to `false` then only requests that specify their own custom
* cache object will be cached.
*
- * # Interceptors
+ * ## Interceptors
*
* Before you start creating interceptors, be sure to understand the
* {@link ng.$q $q and deferred/promise APIs}.
@@ -8256,7 +8306,7 @@ function $HttpProvider() {
* });
* ```
*
- * # Security Considerations
+ * ## Security Considerations
*
* When designing web applications, consider security threats from:
*
@@ -8267,7 +8317,7 @@ function $HttpProvider() {
* pre-configured with strategies that address these issues, but for this to work backend server
* cooperation is required.
*
- * ## JSON Vulnerability Protection
+ * ### JSON Vulnerability Protection
*
* A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
* allows third party website to turn your JSON resource URL into
@@ -8289,7 +8339,7 @@ function $HttpProvider() {
* Angular will strip the prefix, before processing the JSON.
*
*
- * ## Cross Site Request Forgery (XSRF) Protection
+ * ### Cross Site Request Forgery (XSRF) Protection
*
* [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
* an unauthorized site can gain your user's private data. Angular provides a mechanism
@@ -8331,10 +8381,12 @@ function $HttpProvider() {
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
* transform function or an array of such functions. The transform function takes the http
* request body and headers and returns its transformed (typically serialized) version.
+ * See {@link #overriding-the-default-transformations-per-request Overriding the Default Transformations}
* - **transformResponse** –
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
* transform function or an array of such functions. The transform function takes the http
* response body and headers and returns its transformed (typically deserialized) version.
+ * See {@link #overriding-the-default-transformations-per-request Overriding the Default Transformations}
* - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
* GET request, otherwise if a cache instance built with
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
@@ -8817,7 +8869,7 @@ function $HttpProvider() {
function removePendingReq() {
- var idx = indexOf($http.pendingRequests, config);
+ var idx = $http.pendingRequests.indexOf(config);
if (idx !== -1) $http.pendingRequests.splice(idx, 1);
}
}
@@ -8834,7 +8886,7 @@ function $HttpProvider() {
if (isObject(v)) {
if (isDate(v)){
v = v.toISOString();
- } else if (isObject(v)) {
+ } else {
v = toJson(v);
}
}
@@ -9056,7 +9108,6 @@ var $interpolateMinErr = minErr('$interpolate');
/**
* @ngdoc provider
* @name $interpolateProvider
- * @kind function
*
* @description
*
@@ -9372,7 +9423,7 @@ function $InterpolateProvider() {
* @description
* Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
*
- * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change
+ * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
* the symbol.
*
* @returns {string} start symbol.
@@ -9388,7 +9439,7 @@ function $InterpolateProvider() {
* @description
* Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
*
- * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change
+ * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
* the symbol.
*
* @returns {string} end symbol.
@@ -10003,17 +10054,16 @@ LocationHashbangInHtml5Url.prototype =
* Change path, search and hash, when called with parameter and return `$location`.
*
* @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
- * @param {string=} replace The path that will be changed
* @return {string} url
*/
- url: function(url, replace) {
+ url: function(url) {
if (isUndefined(url))
return this.$$url;
var match = PATH_MATCH.exec(url);
if (match[1]) this.path(decodeURIComponent(match[1]));
if (match[2] || match[1]) this.search(match[3] || '');
- this.hash(match[5] || '', replace);
+ this.hash(match[5] || '');
return this;
},
@@ -10071,10 +10121,11 @@ LocationHashbangInHtml5Url.prototype =
* Note: Path should always begin with forward slash (/), this method will add the forward slash
* if it is missing.
*
- * @param {string=} path New path
+ * @param {(string|number)=} path New path
* @return {string} path
*/
path: locationGetterSetter('$$path', function(path) {
+ path = path ? path.toString() : '';
return path.charAt(0) == '/' ? path : '/' + path;
}),
@@ -10110,7 +10161,7 @@ LocationHashbangInHtml5Url.prototype =
* If the argument is a hash object containing an array of values, these values will be encoded
* as duplicate search parameters in the url.
*
- * @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
+ * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
* will override only a single search property.
*
* If `paramValue` is an array, it will override the property of the `search` component of
@@ -10129,7 +10180,8 @@ LocationHashbangInHtml5Url.prototype =
case 0:
return this.$$search;
case 1:
- if (isString(search)) {
+ if (isString(search) || isNumber(search)) {
+ search = search.toString();
this.$$search = parseKeyValue(search);
} else if (isObject(search)) {
// remove object undefined or null properties
@@ -10166,10 +10218,12 @@ LocationHashbangInHtml5Url.prototype =
*
* Change hash fragment when called with parameter and return `$location`.
*
- * @param {string=} hash New hash fragment
+ * @param {(string|number)=} hash New hash fragment
* @return {string} hash
*/
- hash: locationGetterSetter('$$hash', identity),
+ hash: locationGetterSetter('$$hash', function(hash) {
+ return hash ? hash.toString() : '';
+ }),
/**
* @ngdoc method
@@ -10663,12 +10717,21 @@ function ensureSafeFunction(obj, fullExpression) {
}
}
+//Keyword constants
+var CONSTANTS = createMap();
+forEach({
+ 'null': function() { return null; },
+ 'true': function() { return true; },
+ 'false': function() { return false; },
+ 'undefined': function() {}
+}, function(constantGetter, name) {
+ constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;
+ CONSTANTS[name] = constantGetter;
+});
+
+//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
var OPERATORS = extend(createMap(), {
/* jshint bitwise : false */
- 'null':function(){return null;},
- 'true':function(){return true;},
- 'false':function(){return false;},
- undefined:noop,
'+':function(self, locals, a,b){
a=a(self, locals); b=b(self, locals);
if (isDefined(a)) {
@@ -10841,7 +10904,7 @@ Lexer.prototype = {
},
readIdent: function() {
- var parser = this;
+ var expression = this.text;
var ident = '';
var start = this.index;
@@ -10888,30 +10951,11 @@ Lexer.prototype = {
}
}
-
- var token = {
+ this.tokens.push({
index: start,
- text: ident
- };
-
- var fn = OPERATORS[ident];
-
- if (fn) {
- token.fn = fn;
- token.constant = true;
- } else {
- var getter = getterFn(ident, this.options, this.text);
- // TODO(perf): consider exposing the getter reference
- token.fn = extend(function $parsePathGetter(self, locals) {
- return getter(self, locals);
- }, {
- assign: function(self, value) {
- return setter(self, ident, value, parser.text);
- }
- });
- }
-
- this.tokens.push(token);
+ text: ident,
+ fn: CONSTANTS[ident] || getterFn(ident, this.options, expression)
+ });
if (methodName) {
this.tokens.push({
@@ -10980,6 +11024,7 @@ var Parser = function (lexer, $filter, options) {
Parser.ZERO = extend(function () {
return 0;
}, {
+ sharedGetter: true,
constant: true
});
@@ -11114,13 +11159,10 @@ Parser.prototype = {
// TODO(size): maybe we should not support multiple statements?
return (statements.length === 1)
? statements[0]
- : function(self, locals) {
+ : function $parseStatements(self, locals) {
var value;
- for (var i = 0; i < statements.length; i++) {
- var statement = statements[i];
- if (statement) {
- value = statement(self, locals);
- }
+ for (var i = 0, ii = statements.length; i < ii; i++) {
+ value = statements[i](self, locals);
}
return value;
};
@@ -11131,13 +11173,10 @@ Parser.prototype = {
filterChain: function() {
var left = this.expression();
var token;
- while (true) {
- if ((token = this.expect('|'))) {
- left = this.binaryFn(left, token.fn, this.filter());
- } else {
- return left;
- }
+ while ((token = this.expect('|'))) {
+ left = this.binaryFn(left, token.fn, this.filter());
}
+ return left;
},
filter: function() {
@@ -11184,7 +11223,7 @@ Parser.prototype = {
this.text.substring(0, token.index) + '] can not be assigned to', token);
}
right = this.ternary();
- return function(scope, locals) {
+ return function $parseAssignment(scope, locals) {
return left.assign(scope, right(scope, locals), locals);
};
}
@@ -11210,13 +11249,10 @@ Parser.prototype = {
logicalOR: function() {
var left = this.logicalAND();
var token;
- while (true) {
- if ((token = this.expect('||'))) {
- left = this.binaryFn(left, token.fn, this.logicalAND());
- } else {
- return left;
- }
+ while ((token = this.expect('||'))) {
+ left = this.binaryFn(left, token.fn, this.logicalAND());
}
+ return left;
},
logicalAND: function() {
@@ -11278,9 +11314,9 @@ Parser.prototype = {
},
fieldAccess: function(object) {
- var parser = this;
+ var expression = this.text;
var field = this.expect().text;
- var getter = getterFn(field, this.options, this.text);
+ var getter = getterFn(field, this.options, expression);
return extend(function $parseFieldAccess(scope, locals, self) {
return getter(self || object(scope, locals));
@@ -11288,13 +11324,13 @@ Parser.prototype = {
assign: function(scope, value, locals) {
var o = object(scope, locals);
if (!o) object.assign(scope, o = {});
- return setter(o, field, value, parser.text);
+ return setter(o, field, value, expression);
}
});
},
objectIndex: function(obj) {
- var parser = this;
+ var expression = this.text;
var indexFn = this.expression();
this.consume(']');
@@ -11304,15 +11340,15 @@ Parser.prototype = {
i = indexFn(self, locals),
v;
- ensureSafeMemberName(i, parser.text);
+ ensureSafeMemberName(i, expression);
if (!o) return undefined;
- v = ensureSafeObject(o[i], parser.text);
+ v = ensureSafeObject(o[i], expression);
return v;
}, {
assign: function(self, value, locals) {
- var key = ensureSafeMemberName(indexFn(self, locals), parser.text);
+ var key = ensureSafeMemberName(indexFn(self, locals), expression);
// prevent overwriting of Function.constructor which would break ensureSafeObject check
- var o = ensureSafeObject(obj(self, locals), parser.text);
+ var o = ensureSafeObject(obj(self, locals), expression);
if (!o) obj.assign(self, o = {});
return o[key] = value;
}
@@ -11339,7 +11375,7 @@ Parser.prototype = {
if (args) {
var i = argsFn.length;
while (i--) {
- args[i] = argsFn[i](scope, locals);
+ args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);
}
}
@@ -11374,9 +11410,9 @@ Parser.prototype = {
}
this.consume(']');
- return extend(function(self, locals) {
+ return extend(function $parseArrayLiteral(self, locals) {
var array = [];
- for (var i = 0; i < elementFns.length; i++) {
+ for (var i = 0, ii = elementFns.length; i < ii; i++) {
array.push(elementFns[i](self, locals));
}
return array;
@@ -11407,9 +11443,9 @@ Parser.prototype = {
}
this.consume('}');
- return extend(function(self, locals) {
+ return extend(function $parseObjectLiteral(self, locals) {
var object = {};
- for (var i = 0; i < keyValues.length; i++) {
+ for (var i = 0, ii = keyValues.length; i < ii; i++) {
var keyValue = keyValues[i];
object[keyValue.key] = keyValue.value(self, locals);
}
@@ -11427,11 +11463,12 @@ Parser.prototype = {
//////////////////////////////////////////////////
function setter(obj, path, setValue, fullExp) {
+ ensureSafeObject(obj, fullExp);
var element = path.split('.'), key;
for (var i = 0; element.length > 1; i++) {
key = ensureSafeMemberName(element.shift(), fullExp);
- var propertyObj = obj[key];
+ var propertyObj = ensureSafeObject(obj[key], fullExp);
if (!propertyObj) {
propertyObj = {};
obj[key] = propertyObj;
@@ -11439,7 +11476,6 @@ function setter(obj, path, setValue, fullExp) {
obj = propertyObj;
}
key = ensureSafeMemberName(element.shift(), fullExp);
- ensureSafeObject(obj, fullExp);
ensureSafeObject(obj[key], fullExp);
obj[key] = setValue;
return setValue;
@@ -11527,9 +11563,14 @@ function getterFn(path, options, fullExp) {
var evaledFnGetter = new Function('s', 'l', code); // s=scope, l=locals
/* jshint +W054 */
evaledFnGetter.toString = valueFn(code);
+ evaledFnGetter.assign = function(self, value) {
+ return setter(self, path, value, path);
+ };
+
fn = evaledFnGetter;
}
+ fn.sharedGetter = true;
getterFnCache[path] = fn;
return fn;
}
@@ -11580,7 +11621,6 @@ function getterFn(path, options, fullExp) {
/**
* @ngdoc provider
* @name $parseProvider
- * @kind function
*
* @description
* `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
@@ -11597,6 +11637,21 @@ function $ParseProvider() {
this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
$parseOptions.csp = $sniffer.csp;
+ function wrapSharedExpression(exp) {
+ var wrapped = exp;
+
+ if (exp.sharedGetter) {
+ wrapped = function $parseWrapper(self, locals) {
+ return exp(self, locals);
+ };
+ wrapped.literal = exp.literal;
+ wrapped.constant = exp.constant;
+ wrapped.assign = exp.assign;
+ }
+
+ return wrapped;
+ }
+
return function $parse(exp, interceptorFn) {
var parsedExpression, oneTime, cacheKey;
@@ -11619,6 +11674,9 @@ function $ParseProvider() {
if (parsedExpression.constant) {
parsedExpression.$$watchDelegate = constantWatchDelegate;
} else if (oneTime) {
+ //oneTime is not part of the exp passed to the Parser so we may have to
+ //wrap the parsedExpression before adding a $$watchDelegate
+ parsedExpression = wrapSharedExpression(parsedExpression);
parsedExpression.$$watchDelegate = parsedExpression.literal ?
oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
}
@@ -12445,10 +12503,26 @@ function $RootScopeProvider(){
/**
* @ngdoc property
* @name $rootScope.Scope#$id
- * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for
- * debugging.
+ *
+ * @description
+ * Unique scope ID (monotonically increasing) useful for debugging.
*/
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$parent
+ *
+ * @description
+ * Reference to the parent scope.
+ */
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$root
+ *
+ * @description
+ * Reference to the root scope.
+ */
Scope.prototype = {
constructor: Scope,
@@ -13382,7 +13456,7 @@ function $RootScopeProvider(){
var self = this;
return function() {
- namedListeners[indexOf(namedListeners, listener)] = null;
+ namedListeners[namedListeners.indexOf(listener)] = null;
decrementListenerCount(self, 1, name);
};
},
@@ -15273,16 +15347,6 @@ function $WindowProvider(){
* For more information about how angular filters work, and how to create your own filters, see
* {@link guide/filter Filters} in the Angular Developer Guide.
*/
-/**
- * @ngdoc method
- * @name $filterProvider#register
- * @description
- * Register filter factory function.
- *
- * @param {String} name Name of the filter.
- * @param {Function} fn The filter factory function which is injectable.
- */
-
/**
* @ngdoc service
@@ -15321,7 +15385,7 @@ function $FilterProvider($provide) {
/**
* @ngdoc method
- * @name $controllerProvider#register
+ * @name $filterProvider#register
* @param {string|Object} name Name of the filter function, or an object map of filters where
* the keys are the filter names and the values are the filter factories.
* @returns {Object} Registered filter instance, or if a map of filters was provided then a map
@@ -15753,6 +15817,10 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
+ if (number === 0) {
+ isNegative = false;
+ }
+
var fraction = ('' + number).split(DECIMAL_SEP);
var whole = fraction[0];
fraction = fraction[1] || '';
@@ -16353,7 +16421,7 @@ function limitToFilter(){
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
return function(array, sortPredicate, reverseOrder) {
- if (!isArray(array)) return array;
+ if (!(isArrayLike(array))) return array;
if (!sortPredicate) return array;
sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
sortPredicate = map(sortPredicate, function(predicate){
@@ -16894,7 +16962,8 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
};
});
-/* global -nullFormCtrl, -SUBMITTED_CLASS */
+/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true
+ */
var nullFormCtrl = {
$addControl: noop,
$removeControl: noop,
@@ -16917,12 +16986,11 @@ SUBMITTED_CLASS = 'ng-submitted';
* @property {boolean} $invalid True if at least one containing control or form is invalid.
* @property {boolean} $submitted True if user has submitted the form even if its invalid.
*
- * @property {Object} $error Is an object hash, containing references to all invalid controls or
- * forms, where:
+ * @property {Object} $error Is an object hash, containing references to controls or
+ * forms with failing validators, where:
*
* - keys are validation tokens (error names),
- * - values are arrays of controls or forms that are invalid for given error name.
- *
+ * - values are arrays of controls or forms that have a failing validator for given error name.
*
* Built-in validation tokens:
*
@@ -16949,12 +17017,12 @@ FormController.$inject = ['$element', '$attrs', '$scope', '$animate'];
function FormController(element, attrs, $scope, $animate) {
var form = this,
parentForm = element.parent().controller('form') || nullFormCtrl,
- invalidCount = 0, // used to easily determine if we are valid
- pendingCount = 0,
- controls = [],
- errors = form.$error = {};
+ controls = [];