summaryrefslogtreecommitdiffstats
path: root/js/vendor/angular/angular.js
diff options
context:
space:
mode:
authorBernhard Posselt <dev@bernhard-posselt.com>2014-09-02 19:09:58 +0200
committerBernhard Posselt <dev@bernhard-posselt.com>2014-09-02 19:09:58 +0200
commitd52b05965d5761144b1b94e8cc29b5c434a333fb (patch)
treea04e22926d71ea391888fb0bab477be600b4d447 /js/vendor/angular/angular.js
parent29cccccdfbdf9d31a2c242498dd1eb2a88e954de (diff)
update bower deps
Diffstat (limited to 'js/vendor/angular/angular.js')
-rw-r--r--js/vendor/angular/angular.js9397
1 files changed, 6098 insertions, 3299 deletions
diff --git a/js/vendor/angular/angular.js b/js/vendor/angular/angular.js
index 2f26beed6..1f64012df 100644
--- a/js/vendor/angular/angular.js
+++ b/js/vendor/angular/angular.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.2.16
+ * @license AngularJS v1.3.0-rc.0
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
@@ -30,10 +30,13 @@
* should all be static strings, not variables or general expressions.
*
* @param {string} module The namespace to use for the new minErr instance.
+ * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
+ * error from returned function, for cases when a particular type of error is useful.
* @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
*/
-function minErr(module) {
+function minErr(module, ErrorConstructor) {
+ ErrorConstructor = ErrorConstructor || Error;
return function () {
var code = arguments[0],
prefix = '[' + (module ? module + ':' : '') + code + '] ',
@@ -68,101 +71,100 @@ function minErr(module) {
return match;
});
- message = message + '\nhttp://errors.angularjs.org/1.2.16/' +
+ message = message + '\nhttp://errors.angularjs.org/1.3.0-rc.0/' +
(module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) {
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
encodeURIComponent(stringify(arguments[i]));
}
-
- return new Error(message);
+ return new ErrorConstructor(message);
};
}
/* We need to tell jshint what variables are being exported */
-/* global
- -angular,
- -msie,
- -jqLite,
- -jQuery,
- -slice,
- -push,
- -toString,
- -ngMinErr,
- -_angular,
- -angularModule,
- -nodeName_,
- -uid,
-
- -lowercase,
- -uppercase,
- -manualLowercase,
- -manualUppercase,
- -nodeName_,
- -isArrayLike,
- -forEach,
- -sortedKeys,
- -forEachSorted,
- -reverseParams,
- -nextUid,
- -setHashKey,
- -extend,
- -int,
- -inherit,
- -noop,
- -identity,
- -valueFn,
- -isUndefined,
- -isDefined,
- -isObject,
- -isString,
- -isNumber,
- -isDate,
- -isArray,
- -isFunction,
- -isRegExp,
- -isWindow,
- -isScope,
- -isFile,
- -isBlob,
- -isBoolean,
- -trim,
- -isElement,
- -makeMap,
- -map,
- -size,
- -includes,
- -indexOf,
- -arrayRemove,
- -isLeafNode,
- -copy,
- -shallowCopy,
- -equals,
- -csp,
- -concat,
- -sliceArgs,
- -bind,
- -toJsonReplacer,
- -toJson,
- -fromJson,
- -toBoolean,
- -startingTag,
- -tryDecodeURIComponent,
- -parseKeyValue,
- -toKeyValue,
- -encodeUriSegment,
- -encodeUriQuery,
- -angularInit,
- -bootstrap,
- -snake_case,
- -bindJQuery,
- -assertArg,
- -assertArgFn,
- -assertNotHasOwnProperty,
- -getter,
- -getBlockElements,
- -hasOwnProperty,
-
+/* global angular: true,
+ msie: true,
+ jqLite: true,
+ jQuery: true,
+ slice: true,
+ push: true,
+ toString: true,
+ ngMinErr: true,
+ angularModule: true,
+ uid: true,
+ REGEX_STRING_REGEXP: true,
+ VALIDITY_STATE_PROPERTY: true,
+
+ lowercase: true,
+ uppercase: true,
+ manualLowercase: true,
+ manualUppercase: true,
+ nodeName_: true,
+ isArrayLike: true,
+ forEach: true,
+ sortedKeys: true,
+ forEachSorted: true,
+ reverseParams: true,
+ nextUid: true,
+ setHashKey: true,
+ extend: true,
+ int: true,
+ inherit: true,
+ noop: true,
+ identity: true,
+ valueFn: true,
+ isUndefined: true,
+ isDefined: true,
+ isObject: true,
+ isString: true,
+ isNumber: true,
+ isDate: true,
+ isArray: true,
+ isFunction: true,
+ isRegExp: true,
+ isWindow: true,
+ isScope: true,
+ isFile: true,
+ isBlob: true,
+ isBoolean: true,
+ isPromiseLike: true,
+ trim: true,
+ isElement: true,
+ makeMap: true,
+ map: true,
+ size: true,
+ includes: true,
+ indexOf: true,
+ arrayRemove: true,
+ isLeafNode: true,
+ copy: true,
+ shallowCopy: true,
+ equals: true,
+ csp: true,
+ concat: true,
+ sliceArgs: true,
+ bind: true,
+ toJsonReplacer: true,
+ toJson: true,
+ fromJson: true,
+ startingTag: true,
+ tryDecodeURIComponent: true,
+ parseKeyValue: true,
+ toKeyValue: true,
+ encodeUriSegment: true,
+ encodeUriQuery: true,
+ angularInit: true,
+ bootstrap: true,
+ getTestability: true,
+ snake_case: true,
+ bindJQuery: true,
+ assertArg: true,
+ assertArgFn: true,
+ assertNotHasOwnProperty: true,
+ getter: true,
+ getBlockNodes: true,
+ hasOwnProperty: true,
+ createMap: true,
*/
////////////////////////////////////
@@ -182,11 +184,17 @@ function minErr(module) {
* <div doc-module-components="ng"></div>
*/
+var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
+
+// The name of a form control's ValidityState property.
+// This is used so that it's possible for internal tests to create mock ValidityStates.
+var VALIDITY_STATE_PROPERTY = 'validity';
+
/**
* @ngdoc function
* @name angular.lowercase
* @module ng
- * @function
+ * @kind function
*
* @description Converts the specified string to lowercase.
* @param {string} string String to be converted to lowercase.
@@ -199,7 +207,7 @@ var hasOwnProperty = Object.prototype.hasOwnProperty;
* @ngdoc function
* @name angular.uppercase
* @module ng
- * @function
+ * @kind function
*
* @description Converts the specified string to uppercase.
* @param {string} string String to be converted to uppercase.
@@ -240,13 +248,10 @@ var /** holds major version number for IE or NaN for real browsers */
toString = Object.prototype.toString,
ngMinErr = minErr('ng'),
-
- _angular = window.angular,
/** @name angular */
angular = window.angular || (window.angular = {}),
angularModule,
- nodeName_,
- uid = ['0', '0', '0'];
+ uid = 0;
/**
* IE 11 changed the format of the UserAgent string.
@@ -283,7 +288,7 @@ function isArrayLike(obj) {
* @ngdoc function
* @name angular.forEach
* @module ng
- * @function
+ * @kind function
*
* @description
* Invokes the `iterator` function once for each item in `obj` collection, which can be either an
@@ -297,7 +302,7 @@ function isArrayLike(obj) {
```js
var values = {name: 'misko', gender: 'male'};
var log = [];
- angular.forEach(values, function(value, key){
+ angular.forEach(values, function(value, key) {
this.push(key + ': ' + value);
}, log);
expect(log).toEqual(['name: misko', 'gender: male']);
@@ -308,10 +313,11 @@ function isArrayLike(obj) {
* @param {Object=} context Object to become context (`this`) for the iterator function.
* @returns {Object|Array} Reference to `obj`.
*/
+
function forEach(obj, iterator, context) {
- var key;
+ var key, length;
if (obj) {
- if (isFunction(obj)){
+ if (isFunction(obj)) {
for (key in obj) {
// Need to check if hasOwnProperty exists,
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
@@ -319,11 +325,15 @@ function forEach(obj, iterator, context) {
iterator.call(context, obj[key], key);
}
}
+ } 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);
+ }
+ }
} else if (obj.forEach && obj.forEach !== forEach) {
- obj.forEach(iterator, context);
- } else if (isArrayLike(obj)) {
- for (key = 0; key < obj.length; key++)
- iterator.call(context, obj[key], key);
+ obj.forEach(iterator, context);
} else {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
@@ -364,33 +374,17 @@ function reverseParams(iteratorFn) {
}
/**
- * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
- * characters such as '012ABC'. The reason why we are not using simply a number counter is that
- * the number string gets longer over time, and it can also overflow, where as the nextId
- * will grow much slower, it is a string, and it will never overflow.
+ * A consistent way of creating unique IDs in angular.
+ *
+ * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
+ * we hit number precision issues in JavaScript.
+ *
+ * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
*
- * @returns {string} an unique alpha-numeric string
+ * @returns {number} an unique alpha-numeric string
*/
function nextUid() {
- var index = uid.length;
- var digit;
-
- while(index) {
- index--;
- digit = uid[index].charCodeAt(0);
- if (digit == 57 /*'9'*/) {
- uid[index] = 'A';
- return uid.join('');
- }
- if (digit == 90 /*'Z'*/) {
- uid[index] = '0';
- } else {
- uid[index] = String.fromCharCode(digit + 1);
- return uid.join('');
- }
- }
- uid.unshift('0');
- return uid.join('');
+ return ++uid;
}
@@ -412,7 +406,7 @@ function setHashKey(obj, h) {
* @ngdoc function
* @name angular.extend
* @module ng
- * @function
+ * @kind function
*
* @description
* Extends the destination object `dst` by copying all of the properties from the `src` object(s)
@@ -424,9 +418,9 @@ function setHashKey(obj, h) {
*/
function extend(dst) {
var h = dst.$$hashKey;
- forEach(arguments, function(obj){
+ forEach(arguments, function(obj) {
if (obj !== dst) {
- forEach(obj, function(value, key){
+ forEach(obj, function(value, key) {
dst[key] = value;
});
}
@@ -449,7 +443,7 @@ function inherit(parent, extra) {
* @ngdoc function
* @name angular.noop
* @module ng
- * @function
+ * @kind function
*
* @description
* A function that performs no operations. This function can be useful when writing code in the
@@ -469,7 +463,7 @@ noop.$inject = [];
* @ngdoc function
* @name angular.identity
* @module ng
- * @function
+ * @kind function
*
* @description
* A function that returns its first argument. This function is useful when writing code in the
@@ -491,7 +485,7 @@ function valueFn(value) {return function() {return value;};}
* @ngdoc function
* @name angular.isUndefined
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is undefined.
@@ -506,7 +500,7 @@ function isUndefined(value){return typeof value === 'undefined';}
* @ngdoc function
* @name angular.isDefined
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is defined.
@@ -521,7 +515,7 @@ function isDefined(value){return typeof value !== 'undefined';}
* @ngdoc function
* @name angular.isObject
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
@@ -530,14 +524,17 @@ function isDefined(value){return typeof value !== 'undefined';}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Object` but not `null`.
*/
-function isObject(value){return value != null && typeof value === 'object';}
+function isObject(value){
+ // http://jsperf.com/isobject4
+ return value !== null && typeof value === 'object';
+}
/**
* @ngdoc function
* @name angular.isString
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is a `String`.
@@ -552,7 +549,7 @@ function isString(value){return typeof value === 'string';}
* @ngdoc function
* @name angular.isNumber
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is a `Number`.
@@ -567,7 +564,7 @@ function isNumber(value){return typeof value === 'number';}
* @ngdoc function
* @name angular.isDate
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a value is a date.
@@ -575,7 +572,7 @@ function isNumber(value){return typeof value === 'number';}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Date`.
*/
-function isDate(value){
+function isDate(value) {
return toString.call(value) === '[object Date]';
}
@@ -584,7 +581,7 @@ function isDate(value){
* @ngdoc function
* @name angular.isArray
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is an `Array`.
@@ -592,16 +589,13 @@ function isDate(value){
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Array`.
*/
-function isArray(value) {
- return toString.call(value) === '[object Array]';
-}
-
+var isArray = Array.isArray;
/**
* @ngdoc function
* @name angular.isFunction
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is a `Function`.
@@ -632,7 +626,7 @@ function isRegExp(value) {
* @returns {boolean} True if `obj` is a window obj.
*/
function isWindow(obj) {
- return obj && obj.document && obj.location && obj.alert && obj.setInterval;
+ return obj && obj.window === obj;
}
@@ -656,26 +650,21 @@ function isBoolean(value) {
}
-var trim = (function() {
- // native trim is way faster: http://jsperf.com/angular-trim-test
- // but IE doesn't have it... :-(
- // TODO: we should move this into IE/ES5 polyfill
- if (!String.prototype.trim) {
- return function(value) {
- return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
- };
- }
- return function(value) {
- return isString(value) ? value.trim() : value;
- };
-})();
+function isPromiseLike(obj) {
+ return obj && isFunction(obj.then);
+}
+
+
+var trim = function(value) {
+ return isString(value) ? value.trim() : value;
+};
/**
* @ngdoc function
* @name angular.isElement
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if a reference is a DOM element (or wrapped jQuery element).
@@ -693,7 +682,7 @@ function isElement(node) {
* @param str 'key1,key2,...'
* @returns {object} in the form of {key1:true, key2:true, ...}
*/
-function makeMap(str){
+function makeMap(str) {
var obj = {}, items = str.split(","), i;
for ( i = 0; i < items.length; i++ )
obj[ items[i] ] = true;
@@ -701,16 +690,8 @@ function makeMap(str){
}
-if (msie < 9) {
- nodeName_ = function(element) {
- element = element.nodeName ? element : element[0];
- return (element.scopeName && element.scopeName != 'HTML')
- ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
- };
-} else {
- nodeName_ = function(element) {
- return element.nodeName ? element.nodeName : element[0].nodeName;
- };
+function nodeName_(element) {
+ return lowercase(element.nodeName || element[0].nodeName);
}
@@ -740,7 +721,7 @@ function size(obj, ownPropsOnly) {
if (isArray(obj) || isString(obj)) {
return obj.length;
- } else if (isObject(obj)){
+ } else if (isObject(obj)) {
for (key in obj)
if (!ownPropsOnly || obj.hasOwnProperty(key))
count++;
@@ -772,10 +753,10 @@ function arrayRemove(array, value) {
function isLeafNode (node) {
if (node) {
- switch (node.nodeName) {
- case "OPTION":
- case "PRE":
- case "TITLE":
+ switch (nodeName_(node)) {
+ case "option":
+ case "pre":
+ case "title":
return true;
}
}
@@ -786,7 +767,7 @@ function isLeafNode (node) {
* @ngdoc function
* @name angular.copy
* @module ng
- * @function
+ * @kind function
*
* @description
* Creates a deep copy of `source`, which should be an object or an array.
@@ -804,9 +785,9 @@ function isLeafNode (node) {
* @returns {*} The copy or updated `destination`, if `destination` was specified.
*
* @example
- <example>
+ <example module="copyExample">
<file name="index.html">
- <div ng-controller="Controller">
+ <div ng-controller="ExampleController">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
@@ -820,26 +801,27 @@ function isLeafNode (node) {
</div>
<script>
- function Controller($scope) {
- $scope.master= {};
+ angular.module('copyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.master= {};
- $scope.update = function(user) {
- // Example with 1 argument
- $scope.master= angular.copy(user);
- };
+ $scope.update = function(user) {
+ // Example with 1 argument
+ $scope.master= angular.copy(user);
+ };
- $scope.reset = function() {
- // Example with 2 arguments
- angular.copy($scope.master, $scope.user);
- };
+ $scope.reset = function() {
+ // Example with 2 arguments
+ angular.copy($scope.master, $scope.user);
+ };
- $scope.reset();
- }
+ $scope.reset();
+ }]);
</script>
</file>
</example>
*/
-function copy(source, destination){
+function copy(source, destination, stackSource, stackDest) {
if (isWindow(source) || isScope(source)) {
throw ngMinErr('cpws',
"Can't copy! Making copies of Window or Scope instances is not supported.");
@@ -849,52 +831,92 @@ function copy(source, destination){
destination = source;
if (source) {
if (isArray(source)) {
- destination = copy(source, []);
+ destination = copy(source, [], stackSource, stackDest);
} else if (isDate(source)) {
destination = new Date(source.getTime());
} else if (isRegExp(source)) {
- destination = new RegExp(source.source);
+ destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
+ destination.lastIndex = source.lastIndex;
} else if (isObject(source)) {
- destination = copy(source, {});
+ var emptyObject = Object.create(Object.getPrototypeOf(source));
+ destination = copy(source, emptyObject, stackSource, stackDest);
}
}
} else {
if (source === destination) throw ngMinErr('cpi',
"Can't copy! Source and destination are identical.");
+
+ stackSource = stackSource || [];
+ stackDest = stackDest || [];
+
+ if (isObject(source)) {
+ var index = indexOf(stackSource, source);
+ if (index !== -1) return stackDest[index];
+
+ stackSource.push(source);
+ stackDest.push(destination);
+ }
+
+ var result;
if (isArray(source)) {
destination.length = 0;
for ( var i = 0; i < source.length; i++) {
- destination.push(copy(source[i]));
+ result = copy(source[i], null, stackSource, stackDest);
+ if (isObject(source[i])) {
+ stackSource.push(source[i]);
+ stackDest.push(result);
+ }
+ destination.push(result);
}
} else {
var h = destination.$$hashKey;
- forEach(destination, function(value, key){
- delete destination[key];
- });
+ if (isArray(destination)) {
+ destination.length = 0;
+ } else {
+ forEach(destination, function(value, key) {
+ delete destination[key];
+ });
+ }
for ( var key in source) {
- destination[key] = copy(source[key]);
+ if(source.hasOwnProperty(key)) {
+ result = copy(source[key], null, stackSource, stackDest);
+ if (isObject(source[key])) {
+ stackSource.push(source[key]);
+ stackDest.push(result);
+ }
+ destination[key] = result;
+ }
}
setHashKey(destination,h);
}
+
}
return destination;
}
/**
- * Create a shallow copy of an object
+ * Creates a shallow copy of an object, an array or a primitive.
+ *
+ * Assumes that there are no proto properties for objects.
*/
function shallowCopy(src, dst) {
- dst = dst || {};
+ if (isArray(src)) {
+ dst = dst || [];
- for(var key in src) {
- // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
- // so we don't need to worry about using our custom hasOwnProperty here
- if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
- dst[key] = src[key];
+ for (var i = 0, ii = src.length; i < ii; i++) {
+ dst[i] = src[i];
+ }
+ } else if (isObject(src)) {
+ dst = dst || {};
+
+ for (var key in src) {
+ if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
+ dst[key] = src[key];
+ }
}
}
- return dst;
+ return dst || src;
}
@@ -902,7 +924,7 @@ function shallowCopy(src, dst) {
* @ngdoc function
* @name angular.equals
* @module ng
- * @function
+ * @kind function
*
* @description
* Determines if two objects or two values are equivalent. Supports value types, regular
@@ -914,7 +936,7 @@ function shallowCopy(src, dst) {
* * Both objects or values are of the same type and all of their properties are equal by
* comparing them with `angular.equals`.
* * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
- * * Both values represent the same regular expression (In JavasScript,
+ * * Both values represent the same regular expression (In JavaScript,
* /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
* representation matches).
*
@@ -943,7 +965,8 @@ function equals(o1, o2) {
return true;
}
} else if (isDate(o1)) {
- return isDate(o2) && o1.getTime() == o2.getTime();
+ if (!isDate(o2)) return false;
+ return equals(o1.getTime(), o2.getTime());
} else if (isRegExp(o1) && isRegExp(o2)) {
return o1.toString() == o2.toString();
} else {
@@ -967,12 +990,25 @@ function equals(o1, o2) {
return false;
}
+var csp = function() {
+ if (isDefined(csp.isActive_)) return csp.isActive_;
+
+ var active = !!(document.querySelector('[ng-csp]') ||
+ document.querySelector('[data-ng-csp]'));
+
+ if (!active) {
+ try {
+ /* jshint -W031, -W054 */
+ new Function('');
+ /* jshint +W031, +W054 */
+ } catch (e) {
+ active = true;
+ }
+ }
+
+ return (csp.isActive_ = active);
+};
-function csp() {
- return (document.securityPolicy && document.securityPolicy.isActive) ||
- (document.querySelector &&
- !!(document.querySelector('[ng-csp]') || document.querySelector('[data-ng-csp]')));
-}
function concat(array1, array2, index) {
@@ -989,7 +1025,7 @@ function sliceArgs(args, startIndex) {
* @ngdoc function
* @name angular.bind
* @module ng
- * @function
+ * @kind function
*
* @description
* Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
@@ -1027,7 +1063,7 @@ function bind(self, fn) {
function toJsonReplacer(key, value) {
var val = value;
- if (typeof key === 'string' && key.charAt(0) === '$') {
+ if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
val = undefined;
} else if (isWindow(value)) {
val = '$WINDOW';
@@ -1045,10 +1081,10 @@ function toJsonReplacer(key, value) {
* @ngdoc function
* @name angular.toJson
* @module ng
- * @function
+ * @kind function
*
* @description
- * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
+ * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
* stripped since angular uses this notation internally.
*
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
@@ -1065,7 +1101,7 @@ function toJson(obj, pretty) {
* @ngdoc function
* @name angular.fromJson
* @module ng
- * @function
+ * @kind function
*
* @description
* Deserializes a JSON string.
@@ -1080,18 +1116,6 @@ function fromJson(json) {
}
-function toBoolean(value) {
- if (typeof value === 'function') {
- value = true;
- } else if (value && value.length !== 0) {
- var v = lowercase("" + value);
- value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
- } else {
- value = false;
- }
- return value;
-}
-
/**
* @returns {string} Returns the string representation of the element.
*/
@@ -1142,13 +1166,13 @@ function tryDecodeURIComponent(value) {
*/
function parseKeyValue(/**string*/keyValue) {
var obj = {}, key_value, key;
- forEach((keyValue || "").split('&'), function(keyValue){
+ forEach((keyValue || "").split('&'), function(keyValue) {
if ( keyValue ) {
- key_value = keyValue.split('=');
+ key_value = keyValue.replace(/\+/g,'%20').split('=');
key = tryDecodeURIComponent(key_value[0]);
if ( isDefined(key) ) {
var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
- if (!obj[key]) {
+ if (!hasOwnProperty.call(obj, key)) {
obj[key] = val;
} else if(isArray(obj[key])) {
obj[key].push(val);
@@ -1214,9 +1238,23 @@ function encodeUriQuery(val, pctEncodeSpaces) {
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
+ replace(/%3B/gi, ';').
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}
+var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
+
+function getNgAttribute(element, ngAttr) {
+ var attr, i, ii = ngAttrPrefixes.length;
+ element = jqLite(element);
+ for (i=0; i<ii; ++i) {
+ attr = ngAttrPrefixes[i] + ngAttr;
+ if (isString(attr = element.attr(attr))) {
+ return attr;
+ }
+ }
+ return null;
+}
/**
* @ngdoc directive
@@ -1226,6 +1264,11 @@ function encodeUriQuery(val, pctEncodeSpaces) {
* @element ANY
* @param {angular.Module} ngApp an optional application
* {@link angular.module module} name to load.
+ * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
+ * created in "strict-di" mode. This means that the application will fail to invoke functions which
+ * do not use explicit function annotation (and are thus unsuitable for minification), as described
+ * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
+ * tracking down the root of these bugs.
*
* @description
*
@@ -1263,48 +1306,109 @@ function encodeUriQuery(val, pctEncodeSpaces) {
</file>
</example>
*
+ * Using `ngStrictDi`, you would see something like this:
+ *
+ <example ng-app-included="true">
+ <file name="index.html">
+ <div ng-app="ngAppStrictDemo" ng-strict-di>
+ <div ng-controller="GoodController1">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style (see
+ script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="GoodController2">
+ Name: <input ng-model="name"><br />
+ Hello, {{name}}!
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style
+ (see script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="BadController">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>The controller could not be instantiated, due to relying
+ on automatic function annotations (which are disabled in
+ strict mode). As such, the content of this section is not
+ interpolated, and there should be an error in your web console.
+ </p>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngAppStrictDemo', [])
+ // BadController will fail to instantiate, due to relying on automatic function annotation,
+ // rather than an explicit annotation
+ .controller('BadController', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ })
+ // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
+ // due to using explicit annotations using the array style and $inject property, respectively.
+ .controller('GoodController1', ['$scope', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ }])
+ .controller('GoodController2', GoodController2);
+ function GoodController2($scope) {
+ $scope.name = "World";
+ }
+ GoodController2.$inject = ['$scope'];
+ </file>
+ <file name="style.css">
+ div[ng-controller] {
+ margin-bottom: 1em;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ border: 1px solid;
+ padding: .5em;
+ }
+ div[ng-controller^=Good] {
+ border-color: #d6e9c6;
+ background-color: #dff0d8;
+ color: #3c763d;
+ }
+ div[ng-controller^=Bad] {
+ border-color: #ebccd1;
+ background-color: #f2dede;
+ color: #a94442;
+ margin-bottom: 0;
+ }
+ </file>
+ </example>
*/
function angularInit(element, bootstrap) {
- var elements = [element],
- appElement,
+ var appElement,
module,
- names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
- NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
+ config = {};
- function append(element) {
- element && elements.push(element);
- }
+ // The element `element` has priority over any other element
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
- forEach(names, function(name) {
- names[name] = true;
- append(document.getElementById(name));
- name = name.replace(':', '\\:');
- if (element.querySelectorAll) {
- forEach(element.querySelectorAll('.' + name), append);
- forEach(element.querySelectorAll('.' + name + '\\:'), append);
- forEach(element.querySelectorAll('[' + name + ']'), append);
+ if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
+ appElement = element;
+ module = element.getAttribute(name);
}
});
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
+ var candidate;
- forEach(elements, function(element) {
- if (!appElement) {
- var className = ' ' + element.className + ' ';
- var match = NG_APP_CLASS_REGEXP.exec(className);
- if (match) {
- appElement = element;
- module = (match[2] || '').replace(/\s+/g, ',');
- } else {
- forEach(element.attributes, function(attr) {
- if (!appElement && names[attr.name]) {
- appElement = element;
- module = attr.value;
- }
- });
- }
+ if (!appElement && (candidate = element.query