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.js785
1 files changed, 469 insertions, 316 deletions
diff --git a/js/vendor/angular/angular.js b/js/vendor/angular/angular.js
index 754f9aaf6..b740cde01 100644
--- a/js/vendor/angular/angular.js
+++ b/js/vendor/angular/angular.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.3.5
+ * @license AngularJS v1.3.8
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
@@ -54,7 +54,7 @@ function minErr(module, ErrorConstructor) {
return match;
});
- message = message + '\nhttp://errors.angularjs.org/1.3.5/' +
+ message = message + '\nhttp://errors.angularjs.org/1.3.8/' +
(module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) {
message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
@@ -109,6 +109,7 @@ function minErr(module, ErrorConstructor) {
isWindow: true,
isScope: true,
isFile: true,
+ isFormData: true,
isBlob: true,
isBoolean: true,
isPromiseLike: true,
@@ -464,6 +465,8 @@ noop.$inject = [];
return (transformationFn || angular.identity)(value);
};
```
+ * @param {*} value to be returned.
+ * @returns {*} the value passed in.
*/
function identity($) {return $;}
identity.$inject = [];
@@ -630,6 +633,11 @@ function isFile(obj) {
}
+function isFormData(obj) {
+ return toString.call(obj) === '[object FormData]';
+}
+
+
function isBlob(obj) {
return toString.call(obj) === '[object Blob]';
}
@@ -713,7 +721,7 @@ function arrayRemove(array, value) {
* Creates a deep copy of `source`, which should be an object or an array.
*
* * If no destination is supplied, a copy of the object or array is created.
- * * If a destination is provided, all of its elements (for array) or properties (for objects)
+ * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
* are deleted and then all elements/properties from the source are copied to it.
* * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
* * If `source` is identical to 'destination' an exception will be thrown.
@@ -1028,12 +1036,16 @@ function toJsonReplacer(key, value) {
* stripped since angular uses this notation internally.
*
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
- * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
+ * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.
+ * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).
* @returns {string|undefined} JSON-ified string representing `obj`.
*/
function toJson(obj, pretty) {
if (typeof obj === 'undefined') return undefined;
- return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null);
+ if (!isNumber(pretty)) {
+ pretty = pretty ? 2 : null;
+ }
+ return JSON.stringify(obj, toJsonReplacer, pretty);
}
@@ -1047,7 +1059,7 @@ function toJson(obj, pretty) {
* Deserializes a JSON string.
*
* @param {string} json JSON string to deserialize.
- * @returns {Object|Array|string|number} Deserialized thingy.
+ * @returns {Object|Array|string|number} Deserialized JSON string.
*/
function fromJson(json) {
return isString(json)
@@ -1220,7 +1232,7 @@ function getNgAttribute(element, ngAttr) {
* {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
*
* You can specify an **AngularJS module** to be used as the root module for the application. This
- * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
+ * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
* should contain the application code needed or have dependencies on other modules that will
* contain the code. See {@link angular.module} for more information.
*
@@ -1228,7 +1240,7 @@ function getNgAttribute(element, ngAttr) {
* document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
* would not be resolved to `3`.
*
- * `ngApp` is the easiest, and most common, way to bootstrap an application.
+ * `ngApp` is the easiest, and most common way to bootstrap an application.
*
<example module="ngAppDemo">
<file name="index.html">
@@ -1488,7 +1500,12 @@ function reloadWithDebugInfo() {
* @param {DOMElement} element DOM element which is the root of angular application.
*/
function getTestability(rootElement) {
- return angular.element(rootElement).injector().get('$$testability');
+ var injector = angular.element(rootElement).injector();
+ if (!injector) {
+ throw ngMinErr('test',
+ 'no injector found for element argument to getTestability');
+ }
+ return injector.get('$$testability');
}
var SNAKE_CASE_REGEXP = /[A-Z]/g;
@@ -2081,7 +2098,8 @@ function toDebugString(obj) {
$TimeoutProvider,
$$RAFProvider,
$$AsyncCallbackProvider,
- $WindowProvider
+ $WindowProvider,
+ $$jqLiteProvider
*/
@@ -2100,11 +2118,11 @@ function toDebugString(obj) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.3.5', // all of these placeholder strings will be replaced by grunt's
+ full: '1.3.8', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
minor: 3,
- dot: 5,
- codeName: 'cybernetic-mercantilism'
+ dot: 8,
+ codeName: 'prophetic-narwhal'
};
@@ -2234,7 +2252,8 @@ function publishExternalAPI(angular) {
$timeout: $TimeoutProvider,
$window: $WindowProvider,
$$rAF: $$RAFProvider,
- $$asyncCallback: $$AsyncCallbackProvider
+ $$asyncCallback: $$AsyncCallbackProvider,
+ $$jqLite: $$jqLiteProvider
});
}
]);
@@ -3244,6 +3263,27 @@ forEach({
JQLite.prototype.unbind = JQLite.prototype.off;
});
+
+// Provider for private $$jqLite service
+function $$jqLiteProvider() {
+ this.$get = function $$jqLite() {
+ return extend(JQLite, {
+ hasClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteHasClass(node, classes);
+ },
+ addClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteAddClass(node, classes);
+ },
+ removeClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteRemoveClass(node, classes);
+ }
+ });
+ };
+}
+
/**
* Computes a hash of an 'obj'.
* Hash of a:
@@ -3496,6 +3536,7 @@ function annotate(fn, strictDi, name) {
* Return an instance of the service.
*
* @param {string} name The name of the instance to retrieve.
+ * @param {string} caller An optional string to provide the origin of the function call for error messages.
* @return {*} The instance.
*/
@@ -3946,14 +3987,17 @@ function createInjector(modulesToLoad, strictDi) {
}
},
providerInjector = (providerCache.$injector =
- createInternalInjector(providerCache, function() {
+ createInternalInjector(providerCache, function(serviceName, caller) {
+ if (angular.isString(caller)) {
+ path.push(caller);
+ }
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
})),
instanceCache = {},
instanceInjector = (instanceCache.$injector =
- createInternalInjector(instanceCache, function(servicename) {
- var provider = providerInjector.get(servicename + providerSuffix);
- return instanceInjector.invoke(provider.$get, provider, undefined, servicename);
+ createInternalInjector(instanceCache, function(serviceName, caller) {
+ var provider = providerInjector.get(serviceName + providerSuffix, caller);
+ return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
}));
@@ -3988,7 +4032,7 @@ function createInjector(modulesToLoad, strictDi) {
function enforceReturnValue(name, factory) {
return function enforcedReturnValue() {
- var result = instanceInjector.invoke(factory, this, undefined, name);
+ var result = instanceInjector.invoke(factory, this);
if (isUndefined(result)) {
throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
}
@@ -4083,7 +4127,7 @@ function createInjector(modulesToLoad, strictDi) {
function createInternalInjector(cache, factory) {
- function getService(serviceName) {
+ function getService(serviceName, caller) {
if (cache.hasOwnProperty(serviceName)) {
if (cache[serviceName] === INSTANTIATING) {
throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
@@ -4094,7 +4138,7 @@ function createInjector(modulesToLoad, strictDi) {
try {
path.unshift(serviceName);
cache[serviceName] = INSTANTIATING;
- return cache[serviceName] = factory(serviceName);
+ return cache[serviceName] = factory(serviceName, caller);
} catch (err) {
if (cache[serviceName] === INSTANTIATING) {
delete cache[serviceName];
@@ -4126,7 +4170,7 @@ function createInjector(modulesToLoad, strictDi) {
args.push(
locals && locals.hasOwnProperty(key)
? locals[key]
- : getService(key)
+ : getService(key, serviceName)
);
}
if (isArray(fn)) {
@@ -4870,6 +4914,11 @@ function Browser(window, document, $log, $sniffer) {
}
}
+ function getHash(url) {
+ var index = url.indexOf('#');
+ return index === -1 ? '' : url.substr(index + 1);
+ }
+
/**
* @private
* Note: this method is used only by scenario runner
@@ -4999,8 +5048,10 @@ function Browser(window, document, $log, $sniffer) {
}
if (replace) {
location.replace(url);
- } else {
+ } else if (!sameBase) {
location.href = url;
+ } else {
+ location.hash = getHash(url);
}
}
return self;
@@ -5779,7 +5830,7 @@ function $TemplateCacheProvider() {
* #### `multiElement`
* When this property is set to true, the HTML compiler will collect DOM nodes between
* nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
- * together as the directive elements. It is recomended that this feature be used on directives
+ * together as the directive elements. It is recommended that this feature be used on directives
* which are not strictly behavioural (such as {@link ngClick}), and which
* do not manipulate or replace child nodes (such as {@link ngInclude}).
*
@@ -6571,6 +6622,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
};
Attributes.prototype = {
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$normalize
+ * @kind function
+ *
+ * @description
+ * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
+ * `data-`) to its normalized, camelCase form.
+ *
+ * Also there is special case for Moz prefix starting with upper case letter.
+ *
+ * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
+ *
+ * @param {string} name Name to normalize
+ */
$normalize: directiveNormalize,
@@ -7069,7 +7135,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// support ngAttr attribute binding
ngAttrName = directiveNormalize(name);
if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
- name = snake_case(ngAttrName.substr(6), '-');
+ name = name.replace(PREFIX_REGEXP, '')
+ .substr(8).replace(/_(.)/g, function(match, letter) {
+ return letter.toUpperCase();
+ });
}
var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
@@ -7981,7 +8050,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
- var interpolateFn = $interpolate(value, true);
+ var trustedContext = getTrustedContext(node, name);
+ allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
+
+ var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
// no interpolation found -> ignore
if (!interpolateFn) return;
@@ -8006,16 +8078,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
"ng- versions (such as ng-click instead of onclick) instead.");
}
- // If the attribute was removed, then we are done
- if (!attr[name]) {
- return;
+ // If the attribute has changed since last $interpolate()ed
+ var newValue = attr[name];
+ if (newValue !== value) {
+ // we need to interpolate again since the attribute value has been updated
+ // (e.g. by another directive's compile function)
+ // ensure unset/empty values make interpolateFn falsy
+ interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
+ value = newValue;
}
- // we need to interpolate again, in case the attribute value has been updated
- // (e.g. by another directive's compile function)
- interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name),
- ALL_OR_NOTHING_ATTRS[name] || allOrNothing);
-
// if attribute was updated so that there is no interpolation going on we don't want to
// register any observers
if (!interpolateFn) return;
@@ -8149,13 +8221,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
/**
* Converts all accepted directives format into proper directive name.
- * All of these will become 'myDirective':
- * my:Directive
- * my-directive
- * x-my-directive
- * data-my:directive
- *
- * Also there is special case for Moz prefix starting with upper case letter.
* @param name Name to normalize
*/
function directiveNormalize(name) {
@@ -8483,23 +8548,34 @@ function $ExceptionHandlerProvider() {
var APPLICATION_JSON = 'application/json';
var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
-var JSON_START = /^\s*(\[|\{[^\{])/;
-var JSON_END = /[\}\]]\s*$/;
+var JSON_START = /^\[|^\{(?!\{)/;
+var JSON_ENDS = {
+ '[': /]$/,
+ '{': /}$/
+};
var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
function defaultHttpResponseTransform(data, headers) {
if (isString(data)) {
- // strip json vulnerability protection prefix
- data = data.replace(JSON_PROTECTION_PREFIX, '');
- var contentType = headers('Content-Type');
- if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0 && data.trim()) ||
- (JSON_START.test(data) && JSON_END.test(data))) {
- data = fromJson(data);
+ // Strip json vulnerability protection prefix and trim whitespace
+ var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
+
+ if (tempData) {
+ var contentType = headers('Content-Type');
+ if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
+ data = fromJson(tempData);
+ }
}
}
+
return data;
}
+function isJsonLike(str) {
+ var jsonStart = str.match(JSON_START);
+ return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
+}
+
/**
* Parse headers into key value object
*
@@ -8562,16 +8638,17 @@ function headersGetter(headers) {
* This function is used for both request and response transforming
*
* @param {*} data Data to transform.
- * @param {function(string=)} headers Http headers getter fn.
+ * @param {function(string=)} headers HTTP headers getter fn.
+ * @param {number} status HTTP status code of the response.
* @param {(Function|Array.<Function>)} fns Function or an array of functions.
* @returns {*} Transformed data.
*/
-function transformData(data, headers, fns) {
+function transformData(data, headers, status, fns) {
if (isFunction(fns))
- return fns(data, headers);
+ return fns(data, headers, status);
forEach(fns, function(fn) {
- data = fn(data, headers);
+ data = fn(data, headers, status);
});
return data;
@@ -8623,7 +8700,7 @@ function $HttpProvider() {
// transform outgoing request data
transformRequest: [function(d) {
- return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
+ return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
}],
// default headers
@@ -8850,7 +8927,7 @@ function $HttpProvider() {
*
* 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,
+ * the transformed value (`{function(data, headersGetter, status)`) or an array of such transformation functions,
* which allows you to `push` or `unshift` a new transformation function into the transformation chain.
*
* ### Default Transformations
@@ -9094,9 +9171,9 @@ function $HttpProvider() {
* See {@link ng.$http#overriding-the-default-transformations-per-request
* Overriding the Default Transformations}
* - **transformResponse** –
- * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
+ * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
* 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.
+ * response body, headers and status and returns its transformed (typically deserialized) version.
* See {@link ng.$http#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
@@ -9219,24 +9296,23 @@ function $HttpProvider() {
</example>
*/
function $http(requestConfig) {
- var config = {
- method: 'get',
- transformRequest: defaults.transformRequest,
- transformResponse: defaults.transformResponse
- };
- var headers = mergeHeaders(requestConfig);
if (!angular.isObject(requestConfig)) {
throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
}
- extend(config, requestConfig);
- config.headers = headers;
+ var config = extend({
+ method: 'get',
+ transformRequest: defaults.transformRequest,
+ transformResponse: defaults.transformResponse
+ }, requestConfig);
+
+ config.headers = mergeHeaders(requestConfig);
config.method = uppercase(config.method);
var serverRequest = function(config) {
- headers = config.headers;
- var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
+ var headers = config.headers;
+ var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
// strip content-type if data is undefined
if (isUndefined(reqData)) {
@@ -9252,7 +9328,7 @@ function $HttpProvider() {
}
// send request
- return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
+ return sendReq(config, reqData).then(transformResponse, transformResponse);
};
var chain = [serverRequest, undefined];
@@ -9297,13 +9373,30 @@ function $HttpProvider() {
if (!response.data) {
resp.data = response.data;
} else {
- resp.data = transformData(response.data, response.headers, config.transformResponse);
+ resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
}
return (isSuccess(response.status))
? resp
: $q.reject(resp);
}
+ function executeHeaderFns(headers) {
+ var headerContent, processedHeaders = {};
+
+ forEach(headers, function(headerFn, header) {
+ if (isFunction(headerFn)) {
+ headerContent = headerFn();
+ if (headerContent != null) {
+ processedHeaders[header] = headerContent;
+ }
+ } else {
+ processedHeaders[header] = headerFn;
+ }
+ });
+
+ return processedHeaders;
+ }
+
function mergeHeaders(config) {
var defHeaders = defaults.headers,
reqHeaders = extend({}, config.headers),
@@ -9326,23 +9419,7 @@ function $HttpProvider() {
}
// execute if header value is a function for merged headers
- execHeaders(reqHeaders);
- return reqHeaders;
-
- function execHeaders(headers) {
- var headerContent;
-
- forEach(headers, function(headerFn, header) {
- if (isFunction(headerFn)) {
- headerContent = headerFn();
- if (headerContent != null) {
- headers[header] = headerContent;
- } else {
- delete headers[header];
- }
- }
- });
- }
+ return executeHeaderFns(reqHeaders);
}
}
@@ -9485,11 +9562,12 @@ function $HttpProvider() {
* !!! ACCESSES CLOSURE VARS:
* $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
*/
- function sendReq(config, reqData, reqHeaders) {
+ function sendReq(config, reqData) {
var deferred = $q.defer(),
promise = deferred.promise,
cache,
cachedResp,
+ reqHeaders = config.headers,
url = buildUrl(config.url, config.params);
$http.pendingRequests.push(config);
@@ -9508,8 +9586,7 @@ function $HttpProvider() {
if (isDefined(cachedResp)) {
if (isPromiseLike(cachedResp)) {
// cached request has already been sent, but there is no response yet
- cachedResp.then(removePendingReq, removePendingReq);
- return cachedResp;
+ cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
} else {
// serving from cache
if (isArray(cachedResp)) {
@@ -9587,6 +9664,9 @@ function $HttpProvider() {
});
}
+ function resolvePromiseWithResult(result) {
+ resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
+ }
function removePendingReq() {
var idx = $http.pendingRequests.indexOf(config);
@@ -10198,33 +10278,33 @@ function $IntervalProvider() {
* // Don't start a new fight if we are already fighting
* if ( angular.isDefined(stop) ) return;
*
- * stop = $interval(function() {
- * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
- * $scope.blood_1 = $scope.blood_1 - 3;
- * $scope.blood_2 = $scope.blood_2 - 4;
- * } else {
- * $scope.stopFight();
- * }
- * }, 100);
- * };
+ * stop = $interval(function() {
+ * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
+ * $scope.blood_1 = $scope.blood_1 - 3;
+ * $scope.blood_2 = $scope.blood_2 - 4;
+ * } else {
+ * $scope.stopFight();
+ * }
+ * }, 100);
+ * };
*
- * $scope.stopFight = function() {
- * if (angular.isDefined(stop)) {
- * $interval.cancel(stop);
- * stop = undefined;
- * }
- * };
+ * $scope.stopFight = function() {
+ * if (angular.isDefined(stop)) {
+ * $interval.cancel(stop);
+ * stop = undefined;
+ * }
+ * };
*
- * $scope.resetFight = function() {
- * $scope.blood_1 = 100;
- * $scope.blood_2 = 120;
- * };
+ * $scope.resetFight = function() {
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
+ * };
*
- * $scope.$on('$destroy', function() {
- * // Make sure that the interval is destroyed too
- * $scope.stopFight();
- * });
- * }])
+ * $scope.$on('$destroy', function() {
+ * // Make sure that the interval is destroyed too
+ * $scope.stopFight();
+ * });
+ * }])
* // Register the 'myCurrentTime' directive factory method.
* // We inject $interval and dateFilter service since the factory method is DI.
* .directive('myCurrentTime', ['$interval', 'dateFilter',
@@ -10467,6 +10547,10 @@ function stripHash(url) {
return index == -1 ? url : url.substr(0, index);
}
+function trimEmptyHash(url) {
+ return url.replace(/(#.+)|#$/, '$1');
+}
+
function stripFile(url) {
return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
@@ -10578,16 +10662,25 @@ function LocationHashbangUrl(appBase, hashPrefix) {
*/
this.$$parse = function(url) {
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
- var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
- ? beginsWith(hashPrefix, withoutBaseUrl)
- : (this.$$html5)
- ? withoutBaseUrl
- : '';
+ var withoutHashUrl;
+
+ if (withoutBaseUrl.charAt(0) === '#') {
- if (!isString(withoutHashUrl)) {
- throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
- hashPrefix);
+ // The rest of the url starts with a hash so we have
+ // got either a hashbang path or a plain hash fragment
+ withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
+ if (isUndefined(withoutHashUrl)) {
+ // There was no hashbang prefix so we just have a hash fragment
+ withoutHashUrl = withoutBaseUrl;
+ }
+
+ } else {
+ // There was no hashbang path nor hash fragment:
+ // If we are in HTML5 mode we use what is left as the path;
+ // Otherwise we ignore what is left
+ withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
}
+
parseAppUrl(withoutHashUrl, this);
this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
@@ -10950,7 +11043,7 @@ var locationPrototype = {
*
*
* ```js
- * // given url http://example.com/some/path?foo=bar&baz=xoxo#hashValue
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
* var hash = $location.hash();
* // => "hashValue"
* ```
@@ -11174,8 +11267,8 @@ function $LocationProvider() {
* @param {string=} oldState History state object that was before it was changed.
*/
- this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
- function($rootScope, $browser, $sniffer, $rootElement) {
+ this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
+ function($rootScope, $browser, $sniffer, $rootElement, $window) {
var $location,
LocationMode,
baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
@@ -11257,7 +11350,7 @@ function $LocationProvider() {
if ($location.absUrl() != $browser.url()) {
$rootScope.$apply();
// hack to work around FF6 bug 684208 when scenario runner clicks on links
- window.angular['ff-684208-preventDefault'] = true;
+ $window.angular['ff-684208-preventDefault'] = true;
}
}
}
@@ -11302,10 +11395,11 @@ function $LocationProvider() {
// update browser
$rootScope.$watch(function $locationWatch() {
- var oldUrl = $browser.url();
+ var oldUrl = trimEmptyHash($browser.url());
+ var newUrl = trimEmptyHash($location.absUrl());
var oldState = $browser.state();
var currentReplace = $location.$$replace;
- var urlOrStateChanged = oldUrl !== $location.absUrl() ||
+ var urlOrStateChanged = oldUrl !== newUrl ||
($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
if (initializing || urlOrStateChanged) {
@@ -11872,6 +11966,8 @@ Parser.prototype = {
primary = this.arrayDeclaration();
} else if (this.expect('{')) {
primary = this.object();
+ } else if (this.peek().identifier && this.peek().text in CONSTANTS) {
+ primary = CONSTANTS[this.consume().text];
} else if (this.peek().identifier) {
primary = this.identifier();
} else if (this.peek().constant) {
@@ -11974,7 +12070,7 @@ Parser.prototype = {
id += this.consume().text + this.consume().text;
}
- return CONSTANTS[id] || getterFn(id, this.options, this.text);
+ return getterFn(id, this.options, this.text);
},
constant: function() {
@@ -12108,8 +12204,8 @@ Parser.prototype = {
logicalAND: function() {
var left = this.equality();
var token;
- if ((token = this.expect('&&'))) {
- left = this.binaryFn(left, token.text, this.logicalAND(), true);
+ while ((token = this.expect('&&'))) {
+ left = this.binaryFn(left, token.text, this.equality(), true);
}
return left;
},
@@ -12117,8 +12213,8 @@ Parser.prototype = {
equality: function() {
var left = this.relational();
var token;
- if ((token = this.expect('==','!=','===','!=='))) {
- left = this.binaryFn(left, token.text, this.equality());
+ while ((token = this.expect('==','!=','===','!=='))) {
+ left = this.binaryFn(left, token.text, this.relational());
}
return left;
},
@@ -12126,8 +12222,8 @@ Parser.prototype = {
relational: function() {
var left = this.additive();
var token;
- if ((token = this.expect('<', '>', '<=', '>='))) {
- left = this.binaryFn(left, token.text, this.relational());
+ while ((token = this.expect('<', '>', '<=', '>='))) {
+ left = this.binaryFn(left, token.text, this.additive());
}
return left;
},
@@ -12164,17 +12260,16 @@ Parser.prototype = {
},
fieldAccess: function(object) {
- var expression = this.text;
- var field = this.consume().text;
- var getter = getterFn(field, this.options, expression);
+ var getter = this.identifier();
return extend(function $parseFieldAccess(scope, locals, self) {
- return getter(self || object(scope, locals));
+ var o = self || object(scope, locals);
+ return (o == null) ? undefined : getter(o);
}, {
assign: function(scope, value, locals) {
var o = object(scope, locals);
if (!o) object.assign(scope, o = {});
- return setter(o, field, value, expression);
+ return getter.assign(o, value);
}
});
},
@@ -12219,7 +12314,7 @@ Parser.prototype = {
var args = argsFn.length ? [] : null;
return function $parseFunctionCall(scope, locals) {
- var context = contextGetter ? contextGetter(scope, locals) : scope;
+ var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;
var fn = fnGetter(scope, locals, context) || noop;
if (args) {
@@ -13332,12 +13427,10 @@ function qFactory(nextTick, exceptionHandler) {
function $$RAFProvider() { //rAF
this.$get = ['$window', '$timeout', function($window, $timeout) {
var requestAnimationFrame = $window.requestAnimationFrame ||
- $window.webkitRequestAnimationFrame ||
- $window.mozRequestAnimationFrame;
+ $window.webkitRequestAnimationFrame;
var cancelAnimationFrame = $window.cancelAnimationFrame ||
$window.webkitCancelAnimationFrame ||
- $window.mozCancelAnimationFrame ||
$window.webkitCancelRequestAnimationFrame;
var rafSupported = !!requestAnimationFrame;
@@ -13466,7 +13559,6 @@ function $RootScopeProvider() {
var child = parent.$new();
parent.salutation = "Hello";
- child.name = "World";
expect(child.salutation).toEqual('Hello');
child.salutation = "Welcome";
@@ -14104,7 +14196,7 @@ function $RootScopeProvider() {
while (asyncQueue.length) {
try {
asyncTask = asyncQueue.shift();
- asyncTask.scope.$eval(asyncTask.expression);
+ asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
} catch (e) {
$exceptionHandler(e);
}
@@ -14319,8 +14411,9 @@ function $RootScopeProvider() {
* - `string`: execute using the rules as defined in {@link guide/expression expression}.
* - `function(scope)`: execute the function with the current `scope` parameter.
*
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
*/
- $evalAsync: function(expr) {
+ $evalAsync: function(expr, locals) {
// if we are outside of an $digest loop and this is the first time we are scheduling async
// task also schedule async auto-flush
if (!$rootScope.$$phase && !asyncQueue.length) {
@@ -14331,7 +14424,7 @@ function $RootScopeProvider() {
});
}
- asyncQueue.push({scope: this, expression: expr});
+ asyncQueue.push({scope: this, expression: expr, locals: locals});
},
$$postDigest: function(fn) {
@@ -15874,7 +15967,9 @@ function $SnifferProvider() {
// IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
// it. In particular the event is not fired when backspace or delete key are pressed or
// when cut operation is performed.
- if (event == 'input' && msie == 9) return false;
+ // IE10+ implements 'input' event but it erroneously fires under various situations,
+ // e.g. when placeholder changes, or a form is focused.
+ if (event === 'input' && msie <= 11) return false;
if (isUndefined(eventSupport[event])) {
var divElm = document.createElement('div');
@@ -15901,7 +15996,7 @@ var $compileMinErr = minErr('$compile');
* @description
* The `$templateRequest` service downloads the provided template using `$http` and, upon success,
* stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
- * of the HTTP request is empty then a `$compile` error will be thrown (the exception can be thwarted
+ * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
* by setting the 2nd parameter of the function to true).
*
* @param {string} tpl The HTTP request template URL
@@ -15934,10 +16029,8 @@ function $TemplateRequestProvider() {
return $http.get(tpl, httpOptions)
.then(function(response) {
- var html = response.data;
self.totalPendingRequests--;
- $templateCache.put(tpl, html);
- return html;
+ return response.data;
}, handleError);
function handleError(resp) {
@@ -16463,19 +16556,26 @@ function $FilterProvider($provide) {
*
* Can be one of:
*
- * - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
- * the contents of the `array`. All strings or objects with string properties in `array` that contain this string
- * will be returned. The predicate can be negated by prefixing the