diff --git a/gui/default/vendor/angular/README.md b/gui/default/vendor/angular/README.md index 7bdff1ad..f727b0ce 100644 --- a/gui/default/vendor/angular/README.md +++ b/gui/default/vendor/angular/README.md @@ -1,6 +1,6 @@ The files contained herein are: - - angular 1.5.3 + - angular 1.2.9 - angular-translate 2.9.0.1 - angular-translate-loader-static-files 2.11.0 - angular-dirPagination 759009c \ No newline at end of file diff --git a/gui/default/vendor/angular/angular.js b/gui/default/vendor/angular/angular.js index 5e6fb2c3..197110e8 100644 --- a/gui/default/vendor/angular/angular.js +++ b/gui/default/vendor/angular/angular.js @@ -1,6 +1,6 @@ /** - * @license AngularJS v1.5.3 - * (c) 2010-2016 Google, Inc. http://angularjs.org + * @license AngularJS v1.2.9 + * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ (function(window, document, undefined) {'use strict'; @@ -30,168 +30,163 @@ * 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 + * @returns {function(string, string, ...): Error} instance */ -function minErr(module, ErrorConstructor) { - ErrorConstructor = ErrorConstructor || Error; - return function() { - var SKIP_INDEXES = 2; +function minErr(module) { + return function () { + var code = arguments[0], + prefix = '[' + (module ? module + ':' : '') + code + '] ', + template = arguments[1], + templateArgs = arguments, + stringify = function (obj) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (typeof obj === 'undefined') { + return 'undefined'; + } else if (typeof obj !== 'string') { + return JSON.stringify(obj); + } + return obj; + }, + message, i; - var templateArgs = arguments, - code = templateArgs[0], - message = '[' + (module ? module + ':' : '') + code + '] ', - template = templateArgs[1], - paramPrefix, i; + message = prefix + template.replace(/\{\d+\}/g, function (match) { + var index = +match.slice(1, -1), arg; - message += template.replace(/\{\d+\}/g, function(match) { - var index = +match.slice(1, -1), - shiftedIndex = index + SKIP_INDEXES; - - if (shiftedIndex < templateArgs.length) { - return toDebugString(templateArgs[shiftedIndex]); + if (index + 2 < templateArgs.length) { + arg = templateArgs[index + 2]; + if (typeof arg === 'function') { + return arg.toString().replace(/ ?\{[\s\S]*$/, ''); + } else if (typeof arg === 'undefined') { + return 'undefined'; + } else if (typeof arg !== 'string') { + return toJson(arg); + } + return arg; } - return match; }); - message += '\nhttp://errors.angularjs.org/1.5.3/' + + message = message + '\nhttp://errors.angularjs.org/1.2.9/' + (module ? module + '/' : '') + code; - - for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { - message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' + - encodeURIComponent(toDebugString(templateArgs[i])); + for (i = 2; i < arguments.length; i++) { + message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + + encodeURIComponent(stringify(arguments[i])); } - return new ErrorConstructor(message); + return new Error(message); }; } /* We need to tell jshint what variables are being exported */ -/* global angular: true, - msie: true, - jqLite: true, - jQuery: true, - slice: true, - splice: true, - push: true, - toString: true, - ngMinErr: true, - angularModule: true, - uid: true, - REGEX_STRING_REGEXP: true, - VALIDITY_STATE_PROPERTY: true, +/* global + -angular, + -msie, + -jqLite, + -jQuery, + -slice, + -push, + -toString, + -ngMinErr, + -_angular, + -angularModule, + -nodeName_, + -uid, - lowercase: true, - uppercase: true, - manualLowercase: true, - manualUppercase: true, - nodeName_: true, - isArrayLike: true, - forEach: true, - forEachSorted: true, - reverseParams: true, - nextUid: true, - setHashKey: true, - extend: true, - toInt: true, - inherit: true, - merge: true, - noop: true, - identity: true, - valueFn: true, - isUndefined: true, - isDefined: true, - isObject: true, - isBlankObject: true, - isString: true, - isNumber: true, - isDate: true, - isArray: true, - isFunction: true, - isRegExp: true, - isWindow: true, - isScope: true, - isFile: true, - isFormData: true, - isBlob: true, - isBoolean: true, - isPromiseLike: true, - trim: true, - escapeForRegexp: true, - isElement: true, - makeMap: true, - includes: true, - arrayRemove: true, - copy: true, - shallowCopy: true, - equals: true, - csp: true, - jq: true, - concat: true, - sliceArgs: true, - bind: true, - toJsonReplacer: true, - toJson: true, - fromJson: true, - convertTimezoneToLocal: true, - timezoneToOffset: 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, + -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, + -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, - NODE_TYPE_ELEMENT: true, - NODE_TYPE_ATTRIBUTE: true, - NODE_TYPE_TEXT: true, - NODE_TYPE_COMMENT: true, - NODE_TYPE_DOCUMENT: true, - NODE_TYPE_DOCUMENT_FRAGMENT: true, */ //////////////////////////////////// /** - * @ngdoc module - * @name ng - * @module ng - * @description + * @ngdoc function + * @name angular.lowercase + * @function * - * # ng (core module) - * The ng module is loaded by default when an AngularJS application is started. The module itself - * contains the essential components for an AngularJS application to function. The table below - * lists a high level breakdown of each of the services/factories, filters, directives and testing - * components available within this core module. - * - *
+ * @description Converts the specified string to lowercase. + * @param {string} string String to be converted to lowercase. + * @returns {string} Lowercased string. */ +var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;}; -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'; - -var hasOwnProperty = Object.prototype.hasOwnProperty; - -var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; -var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;}; +/** + * @ngdoc function + * @name angular.uppercase + * @function + * + * @description Converts the specified string to uppercase. + * @param {string} string String to be converted to uppercase. + * @returns {string} Uppercased string. + */ +var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;}; var manualLowercase = function(s) { @@ -210,34 +205,38 @@ var manualUppercase = function(s) { // String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish // locale, for this reason we need to detect this case and redefine lowercase/uppercase methods -// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387 +// with correct but slower alternatives. if ('i' !== 'I'.toLowerCase()) { lowercase = manualLowercase; uppercase = manualUppercase; } -var - msie, // holds major version number for IE, or NaN if UA is not IE. +var /** holds major version number for IE or NaN for real browsers */ + msie, jqLite, // delay binding since jQuery could be loaded after us. jQuery, // delay binding slice = [].slice, - splice = [].splice, push = [].push, toString = Object.prototype.toString, - getPrototypeOf = Object.getPrototypeOf, ngMinErr = minErr('ng'), + + _angular = window.angular, /** @name angular */ angular = window.angular || (window.angular = {}), angularModule, - uid = 0; + nodeName_, + uid = ['0', '0', '0']; /** - * documentMode is an IE-only property - * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx + * IE 11 changed the format of the UserAgent string. + * See http://msdn.microsoft.com/en-us/library/ms537503.aspx */ -msie = document.documentMode; +msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]); +if (isNaN(msie)) { + msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]); +} /** @@ -247,99 +246,68 @@ msie = document.documentMode; * String ...) */ function isArrayLike(obj) { + if (obj == null || isWindow(obj)) { + return false; + } - // `null`, `undefined` and `window` are not array-like - if (obj == null || isWindow(obj)) return false; + var length = obj.length; - // arrays, strings and jQuery/jqLite objects are array like - // * jqLite is either the jQuery or jqLite constructor function - // * we have to check the existence of jqLite first as this method is called - // via the forEach method when constructing the jqLite object in the first place - if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true; - - // Support: iOS 8.2 (not reproducible in simulator) - // "length" in obj used to prevent JIT error (gh-11508) - var length = "length" in Object(obj) && obj.length; - - // NodeList objects (with `item` method) and - // other objects with suitable length characteristics are array-like - return isNumber(length) && - (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function'); + if (obj.nodeType === 1 && length) { + return true; + } + return isString(obj) || isArray(obj) || length === 0 || + typeof length === 'number' && length > 0 && (length - 1) in obj; } /** * @ngdoc function * @name angular.forEach - * @module ng - * @kind function + * @function * * @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, 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. + * 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. * - * It is worth noting that `.forEach` does not iterate over inherited properties because it filters + * It is worth nothing that `.forEach` does not iterate over inherited properties because it filters * using the `hasOwnProperty` method. * - * Unlike ES262's - * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), - * providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just - * return the value provided. - * - ```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']);
- ```
+ expect(log).toEqual(['name: misko', 'gender:male']);
+
*
* @param {Object|Array} obj Object to iterate over.
* @param {Function} iterator Iterator function.
* @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, length;
+ var key;
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
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(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, obj);
+ iterator.call(context, obj[key], key);
}
}
} else if (obj.forEach && obj.forEach !== forEach) {
- obj.forEach(iterator, context, obj);
- } else if (isBlankObject(obj)) {
- // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
- for (key in obj) {
- iterator.call(context, obj[key], key, obj);
- }
- } else if (typeof obj.hasOwnProperty === 'function') {
- // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
+ obj.forEach(iterator, context);
+ } else if (isArrayLike(obj)) {
+ for (key = 0; key < obj.length; key++)
+ iterator.call(context, obj[key], key);
+ } else {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
- iterator.call(context, obj[key], key, obj);
- }
- }
- } else {
- // Slow path for objects which do not have a method `hasOwnProperty`
- for (key in obj) {
- if (hasOwnProperty.call(obj, key)) {
- iterator.call(context, obj[key], key, obj);
+ iterator.call(context, obj[key], key);
}
}
}
@@ -347,9 +315,19 @@ function forEach(obj, iterator, context) {
return obj;
}
+function sortedKeys(obj) {
+ var keys = [];
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ keys.push(key);
+ }
+ }
+ return keys.sort();
+}
+
function forEachSorted(obj, iterator, context) {
- var keys = Object.keys(obj).sort();
- for (var i = 0; i < keys.length; i++) {
+ var keys = sortedKeys(obj);
+ for ( var i = 0; i < keys.length; i++) {
iterator.call(context, obj[keys[i]], keys[i]);
}
return keys;
@@ -362,21 +340,37 @@ function forEachSorted(obj, iterator, context) {
* @returns {function(*, string)}
*/
function reverseParams(iteratorFn) {
- return function(value, key) {iteratorFn(key, value);};
+ return function(value, key) { iteratorFn(key, value); };
}
/**
- * A consistent way of creating unique IDs in angular.
+ * 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.
*
- * 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 {number} an unique alpha-numeric string
+ * @returns an unique alpha-numeric string
*/
function nextUid() {
- return ++uid;
+ 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('');
}
@@ -388,117 +382,62 @@ function nextUid() {
function setHashKey(obj, h) {
if (h) {
obj.$$hashKey = h;
- } else {
+ }
+ else {
delete obj.$$hashKey;
}
}
-
-function baseExtend(dst, objs, deep) {
- var h = dst.$$hashKey;
-
- for (var i = 0, ii = objs.length; i < ii; ++i) {
- var obj = objs[i];
- if (!isObject(obj) && !isFunction(obj)) continue;
- var keys = Object.keys(obj);
- for (var j = 0, jj = keys.length; j < jj; j++) {
- var key = keys[j];
- var src = obj[key];
-
- if (deep && isObject(src)) {
- if (isDate(src)) {
- dst[key] = new Date(src.valueOf());
- } else if (isRegExp(src)) {
- dst[key] = new RegExp(src);
- } else if (src.nodeName) {
- dst[key] = src.cloneNode(true);
- } else if (isElement(src)) {
- dst[key] = src.clone();
- } else {
- if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
- baseExtend(dst[key], [src], true);
- }
- } else {
- dst[key] = src;
- }
- }
- }
-
- setHashKey(dst, h);
- return dst;
-}
-
/**
* @ngdoc function
* @name angular.extend
- * @module ng
- * @kind function
+ * @function
*
* @description
- * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
- * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
- * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
- *
- * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
- * {@link angular.merge} for this.
+ * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
+ * to `dst`. You can specify multiple `src` objects.
*
* @param {Object} dst Destination object.
* @param {...Object} src Source object(s).
* @returns {Object} Reference to `dst`.
*/
function extend(dst) {
- return baseExtend(dst, slice.call(arguments, 1), false);
+ var h = dst.$$hashKey;
+ forEach(arguments, function(obj){
+ if (obj !== dst) {
+ forEach(obj, function(value, key){
+ dst[key] = value;
+ });
+ }
+ });
+
+ setHashKey(dst,h);
+ return dst;
}
-
-/**
-* @ngdoc function
-* @name angular.merge
-* @module ng
-* @kind function
-*
-* @description
-* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
-* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
-* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
-*
-* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
-* objects, performing a deep copy.
-*
-* @param {Object} dst Destination object.
-* @param {...Object} src Source object(s).
-* @returns {Object} Reference to `dst`.
-*/
-function merge(dst) {
- return baseExtend(dst, slice.call(arguments, 1), true);
-}
-
-
-
-function toInt(str) {
+function int(str) {
return parseInt(str, 10);
}
function inherit(parent, extra) {
- return extend(Object.create(parent), extra);
+ return extend(new (extend(function() {}, {prototype:parent}))(), extra);
}
/**
* @ngdoc function
* @name angular.noop
- * @module ng
- * @kind function
+ * @function
*
* @description
* A function that performs no operations. This function can be useful when writing code in the
* functional style.
- ```js
+
function foo(callback) {
var result = calculateResult();
(callback || angular.noop)(result);
}
- ```
+
*/
function noop() {}
noop.$inject = [];
@@ -507,37 +446,28 @@ noop.$inject = [];
/**
* @ngdoc function
* @name angular.identity
- * @module ng
- * @kind function
+ * @function
*
* @description
* A function that returns its first argument. This function is useful when writing code in the
* functional style.
*
- ```js
+
function transformer(transformationFn, value) {
return (transformationFn || angular.identity)(value);
};
- ```
- * @param {*} value to be returned.
- * @returns {*} the value passed in.
+
*/
function identity($) {return $;}
identity.$inject = [];
-function valueFn(value) {return function valueRef() {return value;};}
-
-function hasCustomToString(obj) {
- return isFunction(obj.toString) && obj.toString !== toString;
-}
-
+function valueFn(value) {return function() {return value;};}
/**
* @ngdoc function
* @name angular.isUndefined
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a reference is undefined.
@@ -545,14 +475,13 @@ function hasCustomToString(obj) {
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is undefined.
*/
-function isUndefined(value) {return typeof value === 'undefined';}
+function isUndefined(value){return typeof value === 'undefined';}
/**
* @ngdoc function
* @name angular.isDefined
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a reference is defined.
@@ -560,43 +489,28 @@ function isUndefined(value) {return typeof value === 'undefined';}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is defined.
*/
-function isDefined(value) {return typeof value !== 'undefined';}
+function isDefined(value){return typeof value !== 'undefined';}
/**
* @ngdoc function
* @name angular.isObject
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
- * considered to be objects. Note that JavaScript arrays are objects.
+ * considered to be objects.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Object` but not `null`.
*/
-function isObject(value) {
- // http://jsperf.com/isobject4
- return value !== null && typeof value === 'object';
-}
-
-
-/**
- * Determine if a value is an object with a null prototype
- *
- * @returns {boolean} True if `value` is an `Object` with a null prototype
- */
-function isBlankObject(value) {
- return value !== null && typeof value === 'object' && !getPrototypeOf(value);
-}
+function isObject(value){return value != null && typeof value === 'object';}
/**
* @ngdoc function
* @name angular.isString
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a reference is a `String`.
@@ -604,35 +518,27 @@ function isBlankObject(value) {
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `String`.
*/
-function isString(value) {return typeof value === 'string';}
+function isString(value){return typeof value === 'string';}
/**
* @ngdoc function
* @name angular.isNumber
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a reference is a `Number`.
*
- * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
- *
- * If you wish to exclude these then you can use the native
- * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
- * method.
- *
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Number`.
*/
-function isNumber(value) {return typeof value === 'number';}
+function isNumber(value){return typeof value === 'number';}
/**
* @ngdoc function
* @name angular.isDate
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a value is a date.
@@ -640,7 +546,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]';
}
@@ -648,8 +554,7 @@ function isDate(value) {
/**
* @ngdoc function
* @name angular.isArray
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a reference is an `Array`.
@@ -657,13 +562,15 @@ function isDate(value) {
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Array`.
*/
-var isArray = Array.isArray;
+function isArray(value) {
+ return toString.call(value) === '[object Array]';
+}
+
/**
* @ngdoc function
* @name angular.isFunction
- * @module ng
- * @kind function
+ * @function
*
* @description
* Determines if a reference is a `Function`.
@@ -671,7 +578,7 @@ var isArray = Array.isArray;
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Function`.
*/
-function isFunction(value) {return typeof value === 'function';}
+function isFunction(value){return typeof value === 'function';}
/**
@@ -694,7 +601,7 @@ function isRegExp(value) {
* @returns {boolean} True if `obj` is a window obj.
*/
function isWindow(obj) {
- return obj && obj.window === obj;
+ return obj && obj.document && obj.location && obj.alert && obj.setInterval;
}
@@ -708,54 +615,30 @@ function isFile(obj) {
}
-function isFormData(obj) {
- return toString.call(obj) === '[object FormData]';
-}
-
-
-function isBlob(obj) {
- return toString.call(obj) === '[object Blob]';
-}
-
-
function isBoolean(value) {
return typeof value === 'boolean';
}
-function isPromiseLike(obj) {
- return obj && isFunction(obj.then);
-}
-
-
-var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
-function isTypedArray(value) {
- return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
-}
-
-function isArrayBuffer(obj) {
- return toString.call(obj) === '[object ArrayBuffer]';
-}
-
-
-var trim = function(value) {
- return isString(value) ? value.trim() : value;
-};
-
-// Copied from:
-// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
-// Prereq: s is a string.
-var escapeForRegexp = function(s) {
- return s.replace(/([-()\[\]{}+?*.$\^|,:#= 0) {
+ var index = indexOf(array, value);
+ if (index >=0)
array.splice(index, 1);
+ return value;
+}
+
+function isLeafNode (node) {
+ if (node) {
+ switch (node.nodeName) {
+ case "OPTION":
+ case "PRE":
+ case "TITLE":
+ return true;
+ }
}
- return index;
+ return false;
}
/**
* @ngdoc function
* @name angular.copy
- * @module ng
- * @kind function
+ * @function
*
* @description
* 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 arrays) or properties (for objects)
+ * * If a destination is provided, all of its elements (for array) 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.
@@ -820,9 +766,9 @@ function arrayRemove(array, value) {
* @returns {*} The copy or updated `destination`, if `destination` was specified.
*
* @example
- This renders because the controller does not fail to - instantiate, by using explicit annotation style (see - script.js for details) -
-This renders because the controller does not fail to - instantiate, by using explicit annotation style - (see script.js for details) -
-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. -
-
* // Create a new module
* var myModule = angular.module('myModule', []);
*
@@ -1995,28 +1490,28 @@ function setupModuleLoader(window) {
* myModule.value('appName', 'MyCoolApp');
*
* // configure existing services inside initialization blocks.
- * myModule.config(['$locationProvider', function($locationProvider) {
+ * myModule.config(function($locationProvider) {
* // Configure existing providers
* $locationProvider.hashPrefix('!');
- * }]);
- * ```
+ * });
+ *
*
* Then you can create an injector and load your modules like this:
*
- * ```js
- * var injector = angular.injector(['ng', 'myModule'])
- * ```
+ * + * var injector = angular.injector(['ng', 'MyModule']) + ** * However it's more likely that you'll just use * {@link ng.directive:ngApp ngApp} or * {@link angular.bootstrap} to simplify this process for you. * * @param {!string} name The name of the module to create or retrieve. - * @param {!Array.
* module.animation('.animation-name', function($inject1, $inject2) {
* return {
* eventName : function(element, done) {
@@ -2172,86 +1650,64 @@ function setupModuleLoader(window) {
* }
* }
* })
- * ```
+ *
*
- * See {@link ng.$animateProvider#register $animateProvider.register()} and
+ * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
* {@link ngAnimate ngAnimate module} for more information.
*/
- animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
+ animation: invokeLater('$animateProvider', 'register'),
/**
* @ngdoc method
* @name angular.Module#filter
- * @module ng
- * @param {string} name Filter name - this must be a valid angular expression identifier
+ * @methodOf angular.Module
+ * @param {string} name Filter name.
* @param {Function} filterFactory Factory function for creating new instance of filter.
* @description
* See {@link ng.$filterProvider#register $filterProvider.register()}.
- *
- *
* // create an injector
* var $injector = angular.injector(['ng']);
*
* // use the injector to kick off your application
* // use the type inference to auto inject arguments, or use implicit injection
- * $injector.invoke(function($rootScope, $compile, $document) {
+ * $injector.invoke(function($rootScope, $compile, $document){
* $compile($document)($rootScope);
* $rootScope.$digest();
* });
- * ```
+ *
*
* Sometimes you want to get access to the injector of a currently running Angular app
* from outside Angular. Perhaps, you want to inject and compile some markup after the
- * application has been bootstrapped. You can do this using the extra `injector()` added
+ * application has been bootstrapped. You can do this using extra `injector()` added
* to JQuery/jqLite elements. See {@link angular.element}.
*
* *This is fairly rare but could be the case if a third party library is injecting the
@@ -3804,7 +2966,7 @@ var $$HashMapProvider = [function() {
* directive is added to the end of the document body by JQuery. We then compile and link
* it into the current AngularJS scope.
*
- * ```js
+ *
* var $div = $('{{content.label}}');
* $(document.body).append($div);
*
@@ -3812,60 +2974,37 @@ var $$HashMapProvider = [function() {
* var scope = angular.element($div).scope();
* $compile($div)(scope);
* });
- * ```
+ *
*/
/**
- * @ngdoc module
- * @name auto
+ * @ngdoc overview
+ * @name AUTO
* @description
*
- * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
+ * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
*/
-var ARROW_ARG = /^([^\(]+?)=>/;
-var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
+var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var $injectorMinErr = minErr('$injector');
-
-function extractArgs(fn) {
- var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
- args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
- return args;
-}
-
-function anonFn(fn) {
- // For anonymous functions, showing at the very least the function signature can help in
- // debugging.
- var args = extractArgs(fn);
- if (args) {
- return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
- }
- return 'fn';
-}
-
-function annotate(fn, strictDi, name) {
+function annotate(fn) {
var $inject,
+ fnText,
argDecl,
last;
- if (typeof fn === 'function') {
+ if (typeof fn == 'function') {
if (!($inject = fn.$inject)) {
$inject = [];
if (fn.length) {
- if (strictDi) {
- if (!isString(name) || !name) {
- name = fn.name || anonFn(fn);
- }
- throw $injectorMinErr('strictdi',
- '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
- }
- argDecl = extractArgs(fn);
- forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
- arg.replace(FN_ARG, function(all, underscore, name) {
+ fnText = fn.toString().replace(STRIP_COMMENTS, '');
+ argDecl = fnText.match(FN_ARGS);
+ forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
+ arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
@@ -3885,31 +3024,32 @@ function annotate(fn, strictDi, name) {
///////////////////////////////////////
/**
- * @ngdoc service
- * @name $injector
+ * @ngdoc object
+ * @name AUTO.$injector
+ * @function
*
* @description
*
* `$injector` is used to retrieve object instances as defined by
- * {@link auto.$provide provider}, instantiate types, invoke methods,
+ * {@link AUTO.$provide provider}, instantiate types, invoke methods,
* and load modules.
*
* The following always holds true:
*
- * ```js
+ *
* var $injector = angular.injector();
* expect($injector.get('$injector')).toBe($injector);
- * expect($injector.invoke(function($injector) {
+ * expect($injector.invoke(function($injector){
* return $injector;
- * })).toBe($injector);
- * ```
+ * }).toBe($injector);
+ *
*
* # Injection Function Annotation
*
* JavaScript does not have annotations, and annotations are needed for dependency injection. The
* following are all valid ways of annotating function with injection arguments and are equivalent.
*
- * ```js
+ *
* // inferred (only works if code not minified/obfuscated)
* $injector.invoke(function(serviceA){});
*
@@ -3920,18 +3060,16 @@ function annotate(fn, strictDi, name) {
*
* // inline
* $injector.invoke(['serviceA', function(serviceA){}]);
- * ```
+ *
*
* ## Inference
*
* In JavaScript calling `toString()` on a function returns the function definition. The definition
- * can then be parsed and the function arguments can be extracted. This method of discovering
- * annotations is disallowed when the injector is in strict mode.
- * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
- * argument names.
+ * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with
+ * minification, and obfuscation tools since these tools change the argument names.
*
* ## `$inject` Annotation
- * By adding an `$inject` property onto a function the injection parameters can be specified.
+ * By adding a `$inject` property onto a function the injection parameters can be specified.
*
* ## Inline
* As an array of injection names, where the last item in the array is the function to call.
@@ -3939,25 +3077,26 @@ function annotate(fn, strictDi, name) {
/**
* @ngdoc method
- * @name $injector#get
+ * @name AUTO.$injector#get
+ * @methodOf AUTO.$injector
*
* @description
* 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.
*/
/**
* @ngdoc method
- * @name $injector#invoke
+ * @name AUTO.$injector#invoke
+ * @methodOf AUTO.$injector
*
* @description
* Invoke the method and supply the method arguments from the `$injector`.
*
- * @param {Function|Array.
* // Given
* function MyController($scope, $route) {
* // ...
@@ -4012,9 +3154,7 @@ function annotate(fn, strictDi, name) {
*
* // Then
* expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * ```
- *
- * You can disallow this method by using strict injection mode.
+ *
*
* This method does not work with code minification / obfuscation. For this reason the following
* annotation strategies are supported.
@@ -4023,7 +3163,7 @@ function annotate(fn, strictDi, name) {
*
* If a function has an `$inject` property and its value is an array of strings, then the strings
* represent names of services to be injected into the function.
- * ```js
+ *
* // Given
* var MyController = function(obfuscatedScope, obfuscatedRoute) {
* // ...
@@ -4033,7 +3173,7 @@ function annotate(fn, strictDi, name) {
*
* // Then
* expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * ```
+ *
*
* # The array notation
*
@@ -4041,7 +3181,7 @@ function annotate(fn, strictDi, name) {
* is very inconvenient. In these situations using the array notation to specify the dependencies in
* a way that survives minification is a better choice:
*
- * ```js
+ *
* // We wish to write this (not minification / obfuscation safe)
* injector.invoke(function($compile, $rootScope) {
* // ...
@@ -4063,13 +3203,11 @@ function annotate(fn, strictDi, name) {
* expect(injector.annotate(
* ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
* ).toEqual(['$compile', '$rootScope']);
- * ```
+ *
*
- * @param {Function|Array.
* // Define the eventTracker provider
* function EventTrackerProvider() {
* var trackingUrl = '/track';
@@ -4209,110 +3350,102 @@ function annotate(fn, strictDi, name) {
* expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
* }));
* });
- * ```
+ *
*/
/**
* @ngdoc method
- * @name $provide#factory
+ * @name AUTO.$provide#factory
+ * @methodOf AUTO.$provide
* @description
*
* Register a **service factory**, which will be called to return the service instance.
* This is short for registering a service where its provider consists of only a `$get` property,
* which is the given service factory function.
- * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
+ * You should use {@link AUTO.$provide#factory $provide.factory(getFn)} if you do not need to
* configure your service in a provider.
*
* @param {string} name The name of the instance.
- * @param {Function|Array.
* $provide.factory('ping', ['$http', function($http) {
* return function ping() {
* return $http.send('/ping');
* };
* }]);
- * ```
+ *
* You would then inject and use this service like this:
- * ```js
+ *
* someModule.controller('Ctrl', ['ping', function(ping) {
* ping();
* }]);
- * ```
+ *
*/
/**
* @ngdoc method
- * @name $provide#service
+ * @name AUTO.$provide#service
+ * @methodOf AUTO.$provide
* @description
*
* Register a **service constructor**, which will be invoked with `new` to create the service
* instance.
- * This is short for registering a service where its provider's `$get` property is a factory
- * function that returns an instance instantiated by the injector from the service constructor
- * function.
+ * This is short for registering a service where its provider's `$get` property is the service
+ * constructor function that will be used to instantiate the service instance.
*
- * Internally it looks a bit like this:
- *
- * ```
- * {
- * $get: function() {
- * return $injector.instantiate(constructor);
- * }
- * }
- * ```
- *
- *
- * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
+ * You should use {@link AUTO.$provide#methods_service $provide.service(class)} if you define your service
* as a type/class.
*
* @param {string} name The name of the instance.
- * @param {Function|Array.
+ * $provide.service('ping', ['$http', function($http) {
+ * var Ping = function() {
+ * this.$http = $http;
+ * };
+ *
+ * Ping.prototype.send = function() {
+ * return this.$http.get('/ping');
+ * };
+ *
+ * return Ping;
+ * }]);
+ *
* You would then inject and use this service like this:
- * ```js
+ *
* someModule.controller('Ctrl', ['ping', function(ping) {
* ping.send();
* }]);
- * ```
+ *
*/
/**
* @ngdoc method
- * @name $provide#value
+ * @name AUTO.$provide#value
+ * @methodOf AUTO.$provide
* @description
*
- * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
- * number, an array, an object or a function. This is short for registering a service where its
+ * Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a
+ * number, an array, an object or a function. This is short for registering a service where its
* provider's `$get` property is a factory function that takes no arguments and returns the **value
- * service**. That also means it is not possible to inject other services into a value service.
+ * service**.
*
* Value services are similar to constant services, except that they cannot be injected into a
* module configuration function (see {@link angular.Module#config}) but they can be overridden by
- * an Angular {@link auto.$provide#decorator decorator}.
+ * an Angular
+ * {@link AUTO.$provide#decorator decorator}.
*
* @param {string} name The name of the instance.
* @param {*} value The value.
@@ -4320,7 +3453,7 @@ function annotate(fn, strictDi, name) {
*
* @example
* Here are some examples of creating value services.
- * ```js
+ *
* $provide.value('ADMIN_USER', 'admin');
*
* $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
@@ -4328,22 +3461,20 @@ function annotate(fn, strictDi, name) {
* $provide.value('halfOf', function(value) {
* return value / 2;
* });
- * ```
+ *
*/
/**
* @ngdoc method
- * @name $provide#constant
+ * @name AUTO.$provide#constant
+ * @methodOf AUTO.$provide
* @description
*
- * Register a **constant service** with the {@link auto.$injector $injector}, such as a string,
- * a number, an array, an object or a function. Like the {@link auto.$provide#value value}, it is not
- * possible to inject other services into a constant.
- *
- * But unlike {@link auto.$provide#value value}, a constant can be
+ * Register a **constant service**, such as a string, a number, an array, an object or a function,
+ * with the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be
* injected into a module configuration function (see {@link angular.Module#config}) and it cannot
- * be overridden by an Angular {@link auto.$provide#decorator decorator}.
+ * be overridden by an Angular {@link AUTO.$provide#decorator decorator}.
*
* @param {string} name The name of the constant.
* @param {*} value The constant value.
@@ -4351,7 +3482,7 @@ function annotate(fn, strictDi, name) {
*
* @example
* Here a some examples of creating constants:
- * ```js
+ *
* $provide.constant('SHARD_HEIGHT', 306);
*
* $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
@@ -4359,24 +3490,25 @@ function annotate(fn, strictDi, name) {
* $provide.constant('double', function(value) {
* return value * 2;
* });
- * ```
+ *
*/
/**
* @ngdoc method
- * @name $provide#decorator
+ * @name AUTO.$provide#decorator
+ * @methodOf AUTO.$provide
* @description
*
- * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
- * intercepts the creation of a service, allowing it to override or modify the behavior of the
+ * Register a **service decorator** with the {@link AUTO.$injector $injector}. A service decorator
+ * intercepts the creation of a service, allowing it to override or modify the behaviour of the
* service. The object returned by the decorator may be the original service, or a new service
* object which replaces or wraps and delegates to the original service.
*
* @param {string} name The name of the service to decorate.
- * @param {Function|Array.
+ * $provider.decorator('$log', ['$delegate', function($delegate) {
* $delegate.warn = $delegate.error;
* return $delegate;
* }]);
- * ```
+ *
*/
-function createInjector(modulesToLoad, strictDi) {
- strictDi = (strictDi === true);
+function createInjector(modulesToLoad) {
var INSTANTIATING = {},
providerSuffix = 'Provider',
path = [],
- loadedModules = new HashMap([], true),
+ loadedModules = new HashMap(),
providerCache = {
$provide: {
provider: supportObject(provider),
@@ -4411,26 +3542,18 @@ function createInjector(modulesToLoad, strictDi) {
}
},
providerInjector = (providerCache.$injector =
- createInternalInjector(providerCache, function(serviceName, caller) {
- if (angular.isString(caller)) {
- path.push(caller);
- }
+ createInternalInjector(providerCache, function() {
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
})),
instanceCache = {},
- protoInstanceInjector =
- createInternalInjector(instanceCache, function(serviceName, caller) {
- var provider = providerInjector.get(serviceName + providerSuffix, caller);
- return instanceInjector.invoke(
- provider.$get, provider, undefined, serviceName);
- }),
- instanceInjector = protoInstanceInjector;
+ instanceInjector = (instanceCache.$injector =
+ createInternalInjector(instanceCache, function(servicename) {
+ var provider = providerInjector.get(servicename + providerSuffix);
+ return instanceInjector.invoke(provider.$get, provider);
+ }));
- providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) };
- var runBlocks = loadModules(modulesToLoad);
- instanceInjector = protoInstanceInjector.get('$injector');
- instanceInjector.strictDi = strictDi;
- forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); });
+
+ forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
return instanceInjector;
@@ -4459,21 +3582,7 @@ function createInjector(modulesToLoad, strictDi) {
return providerCache[name + providerSuffix] = provider_;
}
- function enforceReturnValue(name, factory) {
- return function enforcedReturnValue() {
- var result = instanceInjector.invoke(factory, this);
- if (isUndefined(result)) {
- throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
- }
- return result;
- };
- }
-
- function factory(name, factoryFn, enforce) {
- return provider(name, {
- $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
- });
- }
+ function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
@@ -4481,7 +3590,7 @@ function createInjector(modulesToLoad, strictDi) {
}]);
}
- function value(name, val) { return factory(name, valueFn(val), false); }
+ function value(name, val) { return factory(name, valueFn(val)); }
function constant(name, value) {
assertNotHasOwnProperty(name, 'constant');
@@ -4502,29 +3611,23 @@ function createInjector(modulesToLoad, strictDi) {
////////////////////////////////////
// Module Loading
////////////////////////////////////
- function loadModules(modulesToLoad) {
- assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');
- var runBlocks = [], moduleFn;
+ function loadModules(modulesToLoad){
+ var runBlocks = [], moduleFn, invokeQueue, i, ii;
forEach(modulesToLoad, function(module) {
if (loadedModules.get(module)) return;
loadedModules.put(module, true);
- function runInvokeQueue(queue) {
- var i, ii;
- for (i = 0, ii = queue.length; i < ii; i++) {
- var invokeArgs = queue[i],
- provider = providerInjector.get(invokeArgs[0]);
-
- provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
- }
- }
-
try {
if (isString(module)) {
moduleFn = angularModule(module);
runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
- runInvokeQueue(moduleFn._invokeQueue);
- runInvokeQueue(moduleFn._configBlocks);
+
+ for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
+ var invokeArgs = invokeQueue[i],
+ provider = providerInjector.get(invokeArgs[0]);
+
+ provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
+ }
} else if (isFunction(module)) {
runBlocks.push(providerInjector.invoke(module));
} else if (isArray(module)) {
@@ -4557,18 +3660,17 @@ function createInjector(modulesToLoad, strictDi) {
function createInternalInjector(cache, factory) {
- function getService(serviceName, caller) {
+ function getService(serviceName) {
if (cache.hasOwnProperty(serviceName)) {
if (cache[serviceName] === INSTANTIATING) {
- throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
- serviceName + ' <- ' + path.join(' <- '));
+ throw $injectorMinErr('cdep', 'Circular dependency found: {0}', path.join(' <- '));
}
return cache[serviceName];
} else {
try {
path.unshift(serviceName);
cache[serviceName] = INSTANTIATING;
- return cache[serviceName] = factory(serviceName, caller);
+ return cache[serviceName] = factory(serviceName);
} catch (err) {
if (cache[serviceName] === INSTANTIATING) {
delete cache[serviceName];
@@ -4580,72 +3682,52 @@ function createInjector(modulesToLoad, strictDi) {
}
}
-
- function injectionArgs(fn, locals, serviceName) {
+ function invoke(fn, self, locals){
var args = [],
- $inject = createInjector.$$annotate(fn, strictDi, serviceName);
+ $inject = annotate(fn),
+ length, i,
+ key;
- for (var i = 0, length = $inject.length; i < length; i++) {
- var key = $inject[i];
+ for(i = 0, length = $inject.length; i < length; i++) {
+ key = $inject[i];
if (typeof key !== 'string') {
throw $injectorMinErr('itkn',
'Incorrect injection token! Expected service name as string, got {0}', key);
}
- args.push(locals && locals.hasOwnProperty(key) ? locals[key] :
- getService(key, serviceName));
+ args.push(
+ locals && locals.hasOwnProperty(key)
+ ? locals[key]
+ : getService(key)
+ );
}
- return args;
+ if (!fn.$inject) {
+ // this means that we must be an array.
+ fn = fn[length];
+ }
+
+ // http://jsperf.com/angularjs-invoke-apply-vs-switch
+ // #5388
+ return fn.apply(self, args);
}
- function isClass(func) {
- // IE 9-11 do not support classes and IE9 leaks with the code below.
- if (msie <= 11) {
- return false;
- }
- // Workaround for MS Edge.
- // Check https://connect.microsoft.com/IE/Feedback/Details/2211653
- return typeof func === 'function'
- && /^(?:class\s|constructor\()/.test(Function.prototype.toString.call(func));
- }
+ function instantiate(Type, locals) {
+ var Constructor = function() {},
+ instance, returnedValue;
- function invoke(fn, self, locals, serviceName) {
- if (typeof locals === 'string') {
- serviceName = locals;
- locals = null;
- }
-
- var args = injectionArgs(fn, locals, serviceName);
- if (isArray(fn)) {
- fn = fn[fn.length - 1];
- }
-
- if (!isClass(fn)) {
- // http://jsperf.com/angularjs-invoke-apply-vs-switch
- // #5388
- return fn.apply(self, args);
- } else {
- args.unshift(null);
- return new (Function.prototype.bind.apply(fn, args))();
- }
- }
-
-
- function instantiate(Type, locals, serviceName) {
// Check if Type is annotated and use just the given function at n-1 as parameter
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
- var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
- var args = injectionArgs(Type, locals, serviceName);
- // Empty object at position 0 is ignored for invocation with `new`, but required.
- args.unshift(null);
- return new (Function.prototype.bind.apply(ctor, args))();
- }
+ Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
+ instance = new Constructor();
+ returnedValue = invoke(Type, instance, locals);
+ return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
+ }
return {
invoke: invoke,
instantiate: instantiate,
get: getService,
- annotate: createInjector.$$annotate,
+ annotate: annotate,
has: function(name) {
return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
}
@@ -4653,272 +3735,99 @@ function createInjector(modulesToLoad, strictDi) {
}
}
-createInjector.$$annotate = annotate;
-
/**
- * @ngdoc provider
- * @name $anchorScrollProvider
+ * @ngdoc function
+ * @name ng.$anchorScroll
+ * @requires $window
+ * @requires $location
+ * @requires $rootScope
*
* @description
- * Use `$anchorScrollProvider` to disable automatic scrolling whenever
- * {@link ng.$location#hash $location.hash()} changes.
+ * When called, it checks current value of `$location.hash()` and scroll to related element,
+ * according to rules specified in
+ * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.
+ *
+ * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
+ * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
+ *
+ * @example
+
* return {
- * //enter, leave, move signature
- * eventFn : function(element, done, options) {
- * //code to run the animation
- * //once complete, then run done()
- * return function endFunction(wasCancelled) {
- * //code to cancel the animation
- * }
- * }
- * }
- * ```
+ * eventFn : function(element, done) {
+ * //code to run the animation
+ * //once complete, then run done()
+ * return function cancellationFunction() {
+ * //code to cancel the animation
+ * }
+ * }
+ * }
+ *
*
- * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to).
- * @param {Function} factory The factory function that will be executed to return the animation
+ * @param {string} name The name of the animation.
+ * @param {function} factory The factory function that will be executed to return the animation
* object.
*/
this.register = function(name, factory) {
- if (name && name.charAt(0) !== '.') {
- throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name);
- }
-
var key = name + '-animation';
- provider.$$registeredAnimations[name.substr(1)] = key;
+ if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
+ "Expecting class selector starting with '.' got '{0}'.", name);
+ this.$$selectors[name.substr(1)] = key;
$provide.factory(key, factory);
};
/**
- * @ngdoc method
- * @name $animateProvider#classNameFilter
+ * @ngdoc function
+ * @name ng.$animateProvider#classNameFilter
+ * @methodOf ng.$animateProvider
*
* @description
* Sets and/or returns the CSS class regular expression that is checked when performing
* an animation. Upon bootstrap the classNameFilter value is not set at all and will
- * therefore enable $animate to attempt to perform an animation on any element that is triggered.
- * When setting the `classNameFilter` value, animations will only be performed on elements
+ * therefore enable $animate to attempt to perform an animation on any element.
+ * When setting the classNameFilter value, animations will only be performed on elements
* that successfully match the filter expression. This in turn can boost performance
* for low-powered devices as well as applications containing a lot of structural operations.
* @param {RegExp=} expression The className expression which will be checked against all animations
* @return {RegExp} The current CSS className expression value. If null then there is no expression value
*/
this.classNameFilter = function(expression) {
- if (arguments.length === 1) {
+ if(arguments.length === 1) {
this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
- if (this.$$classNameFilter) {
- var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)");
- if (reservedRegex.test(this.$$classNameFilter.toString())) {
- throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME);
-
- }
- }
}
return this.$$classNameFilter;
};
- this.$get = ['$$animateQueue', function($$animateQueue) {
- function domInsert(element, parentElement, afterElement) {
- // if for some reason the previous element was removed
- // from the dom sometime before this code runs then let's
- // just stick to using the parent element as the anchor
- if (afterElement) {
- var afterNode = extractElementNode(afterElement);
- if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) {
- afterElement = null;
- }
- }
- afterElement ? afterElement.after(element) : parentElement.prepend(element);
- }
+ this.$get = ['$timeout', function($timeout) {
/**
- * @ngdoc service
- * @name $animate
- * @description The $animate service exposes a series of DOM utility methods that provide support
- * for animation hooks. The default behavior is the application of DOM operations, however,
- * when an animation is detected (and animations are enabled), $animate will do the heavy lifting
- * to ensure that animation runs with the triggered DOM operation.
*
- * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't
- * included and only when it is active then the animation hooks that `$animate` triggers will be
- * functional. Once active then all structural `ng-` directives will trigger animations as they perform
- * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
- * `ngShow`, `ngHide` and `ngMessages` also provide support for animations.
+ * @ngdoc object
+ * @name ng.$animate
+ * @description The $animate service provides rudimentary DOM manipulation functions to
+ * insert, remove and move elements within the DOM, as well as adding and removing classes.
+ * This service is the core service used by the ngAnimate $animator service which provides
+ * high-level animation hooks for CSS and JavaScript.
*
- * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives.
+ * $animate is available in the AngularJS core, however, the ngAnimate module must be included
+ * to enable full out animation support. Otherwise, $animate will only perform simple DOM
+ * manipulation operations.
*
- * To learn more about enabling animation support, click here to visit the
- * {@link ngAnimate ngAnimate module page}.
+ * To learn more about enabling animation support, click here to visit the {@link ngAnimate
+ * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
+ * page}.
*/
return {
- // we don't call it directly since non-existant arguments may
- // be interpreted as null within the sub enabled function
/**
*
- * @ngdoc method
- * @name $animate#on
- * @kind function
- * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...)
- * has fired on the given element or among any of its children. Once the listener is fired, the provided callback
- * is fired with the following params:
- *
- * ```js
- * $animate.on('enter', container,
- * function callback(element, phase) {
- * // cool we detected an enter animation within the container
- * }
- * );
- * ```
- *
- * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...)
- * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself
- * as well as among its children
- * @param {Function} callback the callback function that will be fired when the listener is triggered
- *
- * The arguments present in the callback function are:
- * * `element` - The captured DOM element that the animation was fired on.
- * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends).
+ * @ngdoc function
+ * @name ng.$animate#enter
+ * @methodOf ng.$animate
+ * @function
+ * @description Inserts the element into the DOM either after the `after` element or within
+ * the `parent` element. Once complete, the done() callback will be fired (if provided).
+ * @param {jQuery/jqLite element} element the element which will be inserted into the DOM
+ * @param {jQuery/jqLite element} parent the parent element which will append the element as
+ * a child (if the after element is not present)
+ * @param {jQuery/jqLite element} after the sibling element which will append the element
+ * after itself
+ * @param {function=} done callback function that will be called after the element has been
+ * inserted into the DOM
*/
- on: $$animateQueue.on,
-
- /**
- *
- * @ngdoc method
- * @name $animate#off
- * @kind function
- * @description Deregisters an event listener based on the event which has been associated with the provided element. This method
- * can be used in three different ways depending on the arguments:
- *
- * ```js
- * // remove all the animation event listeners listening for `enter`
- * $animate.off('enter');
- *
- * // remove all the animation event listeners listening for `enter` on the given element and its children
- * $animate.off('enter', container);
- *
- * // remove the event listener function provided by `callback` that is set
- * // to listen for `enter` on the given `container` as well as its children
- * $animate.off('enter', container, callback);
- * ```
- *
- * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
- * @param {DOMElement=} container the container element the event listener was placed on
- * @param {Function=} callback the callback function that was registered as the listener
- */
- off: $$animateQueue.off,
-
- /**
- * @ngdoc method
- * @name $animate#pin
- * @kind function
- * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists
- * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the
- * element despite being outside the realm of the application or within another application. Say for example if the application
- * was bootstrapped on an element that is somewhere inside of the `` tag, but we wanted to allow for an element to be situated
- * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind
- * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association.
- *
- * Note that this feature is only active when the `ngAnimate` module is used.
- *
- * @param {DOMElement} element the external element that will be pinned
- * @param {DOMElement} parentElement the host parent element that will be associated with the external element
- */
- pin: $$animateQueue.pin,
-
- /**
- *
- * @ngdoc method
- * @name $animate#enabled
- * @kind function
- * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This
- * function can be called in four ways:
- *
- * ```js
- * // returns true or false
- * $animate.enabled();
- *
- * // changes the enabled state for all animations
- * $animate.enabled(false);
- * $animate.enabled(true);
- *
- * // returns true or false if animations are enabled for an element
- * $animate.enabled(element);
- *
- * // changes the enabled state for an element and its children
- * $animate.enabled(element, true);
- * $animate.enabled(element, false);
- * ```
- *
- * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state
- * @param {boolean=} enabled whether or not the animations will be enabled for the element
- *
- * @return {boolean} whether or not animations are enabled
- */
- enabled: $$animateQueue.enabled,
-
- /**
- * @ngdoc method
- * @name $animate#cancel
- * @kind function
- * @description Cancels the provided animation.
- *
- * @param {Promise} animationPromise The animation promise that is returned when an animation is started.
- */
- cancel: function(runner) {
- runner.end && runner.end();
+ enter : function(element, parent, after, done) {
+ if (after) {
+ after.after(element);
+ } else {
+ if (!parent || !parent[0]) {
+ parent = after.parent();
+ }
+ parent.append(element);
+ }
+ done && $timeout(done, 0, false);
},
/**
*
- * @ngdoc method
- * @name $animate#enter
- * @kind function
- * @description Inserts the element into the DOM either after the `after` element (if provided) or
- * as the first child within the `parent` element and then triggers an animation.
- * A promise is returned that will be resolved during the next digest once the animation
- * has completed.
- *
- * @param {DOMElement} element the element which will be inserted into the DOM
- * @param {DOMElement} parent the parent element which will append the element as
- * a child (so long as the after element is not present)
- * @param {DOMElement=} after the sibling element after which the element will be appended
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
+ * @ngdoc function
+ * @name ng.$animate#leave
+ * @methodOf ng.$animate
+ * @function
+ * @description Removes the element from the DOM. Once complete, the done() callback will be
+ * fired (if provided).
+ * @param {jQuery/jqLite element} element the element which will be removed from the DOM
+ * @param {function=} done callback function that will be called after the element has been
+ * removed from the DOM
*/
- enter: function(element, parent, after, options) {
- parent = parent && jqLite(parent);
- after = after && jqLite(after);
- parent = parent || after.parent();
- domInsert(element, parent, after);
- return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options));
+ leave : function(element, done) {
+ element.remove();
+ done && $timeout(done, 0, false);
},
/**
*
- * @ngdoc method
- * @name $animate#move
- * @kind function
- * @description Inserts (moves) the element into its new position in the DOM either after
- * the `after` element (if provided) or as the first child within the `parent` element
- * and then triggers an animation. A promise is returned that will be resolved
- * during the next digest once the animation has completed.
- *
- * @param {DOMElement} element the element which will be moved into the new DOM position
- * @param {DOMElement} parent the parent element which will append the element as
- * a child (so long as the after element is not present)
- * @param {DOMElement=} after the sibling element after which the element will be appended
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
+ * @ngdoc function
+ * @name ng.$animate#move
+ * @methodOf ng.$animate
+ * @function
+ * @description Moves the position of the provided element within the DOM to be placed
+ * either after the `after` element or inside of the `parent` element. Once complete, the
+ * done() callback will be fired (if provided).
+ *
+ * @param {jQuery/jqLite element} element the element which will be moved around within the
+ * DOM
+ * @param {jQuery/jqLite element} parent the parent element where the element will be
+ * inserted into (if the after element is not present)
+ * @param {jQuery/jqLite element} after the sibling element where the element will be
+ * positioned next to
+ * @param {function=} done the callback function (if provided) that will be fired after the
+ * element has been moved to its new position
*/
- move: function(element, parent, after, options) {
- parent = parent && jqLite(parent);
- after = after && jqLite(after);
- parent = parent || after.parent();
- domInsert(element, parent, after);
- return $$animateQueue.push(element, 'move', prepareAnimateOptions(options));
+ move : function(element, parent, after, done) {
+ // Do not remove element before insert. Removing will cause data associated with the
+ // element to be dropped. Insert will implicitly do the remove.
+ this.enter(element, parent, after, done);
},
/**
- * @ngdoc method
- * @name $animate#leave
- * @kind function
- * @description Triggers an animation and then removes the element from the DOM.
- * When the function is called a promise is returned that will be resolved during the next
- * digest once the animation has completed.
*
- * @param {DOMElement} element the element which will be removed from the DOM
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
+ * @ngdoc function
+ * @name ng.$animate#addClass
+ * @methodOf ng.$animate
+ * @function
+ * @description Adds the provided className CSS class value to the provided element. Once
+ * complete, the done() callback will be fired (if provided).
+ * @param {jQuery/jqLite element} element the element which will have the className value
+ * added to it
+ * @param {string} className the CSS class which will be added to the element
+ * @param {function=} done the callback function (if provided) that will be fired after the
+ * className value has been added to the element
*/
- leave: function(element, options) {
- return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {
- element.remove();
+ addClass : function(element, className, done) {
+ className = isString(className) ?
+ className :
+ isArray(className) ? className.join(' ') : '';
+ forEach(element, function (element) {
+ jqLiteAddClass(element, className);
});
+ done && $timeout(done, 0, false);
},
/**
- * @ngdoc method
- * @name $animate#addClass
- * @kind function
*
- * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon
- * execution, the addClass operation will only be handled after the next digest and it will not trigger an
- * animation if element already contains the CSS class or if the class is removed at a later step.
- * Note that class-based animations are treated differently compared to structural animations
- * (like enter, move and leave) since the CSS classes may be added/removed at different points
- * depending if CSS or JavaScript animations are used.
- *
- * @param {DOMElement} element the element which the CSS classes will be applied to
- * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
+ * @ngdoc function
+ * @name ng.$animate#removeClass
+ * @methodOf ng.$animate
+ * @function
+ * @description Removes the provided className CSS class value from the provided element.
+ * Once complete, the done() callback will be fired (if provided).
+ * @param {jQuery/jqLite element} element the element which will have the className value
+ * removed from it
+ * @param {string} className the CSS class which will be removed from the element
+ * @param {function=} done the callback function (if provided) that will be fired after the
+ * className value has been removed from the element
*/
- addClass: function(element, className, options) {
- options = prepareAnimateOptions(options);
- options.addClass = mergeClasses(options.addclass, className);
- return $$animateQueue.push(element, 'addClass', options);
+ removeClass : function(element, className, done) {
+ className = isString(className) ?
+ className :
+ isArray(className) ? className.join(' ') : '';
+ forEach(element, function (element) {
+ jqLiteRemoveClass(element, className);
+ });
+ done && $timeout(done, 0, false);
},
- /**
- * @ngdoc method
- * @name $animate#removeClass
- * @kind function
- *
- * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon
- * execution, the removeClass operation will only be handled after the next digest and it will not trigger an
- * animation if element does not contain the CSS class or if the class is added at a later step.
- * Note that class-based animations are treated differently compared to structural animations
- * (like enter, move and leave) since the CSS classes may be added/removed at different points
- * depending if CSS or JavaScript animations are used.
- *
- * @param {DOMElement} element the element which the CSS classes will be applied to
- * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- removeClass: function(element, className, options) {
- options = prepareAnimateOptions(options);
- options.removeClass = mergeClasses(options.removeClass, className);
- return $$animateQueue.push(element, 'removeClass', options);
- },
-
- /**
- * @ngdoc method
- * @name $animate#setClass
- * @kind function
- *
- * @description Performs both the addition and removal of a CSS classes on an element and (during the process)
- * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and
- * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has
- * passed. Note that class-based animations are treated differently compared to structural animations
- * (like enter, move and leave) since the CSS classes may be added/removed at different points
- * depending if CSS or JavaScript animations are used.
- *
- * @param {DOMElement} element the element which the CSS classes will be applied to
- * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces)
- * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- setClass: function(element, add, remove, options) {
- options = prepareAnimateOptions(options);
- options.addClass = mergeClasses(options.addClass, add);
- options.removeClass = mergeClasses(options.removeClass, remove);
- return $$animateQueue.push(element, 'setClass', options);
- },
-
- /**
- * @ngdoc method
- * @name $animate#animate
- * @kind function
- *
- * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
- * If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take
- * on the provided styles. For example, if a transition animation is set for the given classNamem, then the provided `from` and
- * `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding
- * style in `to`, the style in `from` is applied immediately, and no animation is run.
- * If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate`
- * method (or as part of the `options` parameter):
- *
- * ```js
- * ngModule.animation('.my-inline-animation', function() {
- * return {
- * animate : function(element, from, to, done, options) {
- * //animation
- * done();
- * }
- * }
- * });
- * ```
- *
- * @param {DOMElement} element the element which the CSS styles will be applied to
- * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
- * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
- * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
- * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
- * (Note that if no animation is detected then this value will not be applied to the element.)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- animate: function(element, from, to, className, options) {
- options = prepareAnimateOptions(options);
- options.from = options.from ? extend(options.from, from) : from;
- options.to = options.to ? extend(options.to, to) : to;
-
- className = className || 'ng-inline-animate';
- options.tempClasses = mergeClasses(options.tempClasses, className);
- return $$animateQueue.push(element, 'animate', options);
- }
+ enabled : noop
};
}];
}];
-var $$AnimateAsyncRunFactoryProvider = function() {
- this.$get = ['$$rAF', function($$rAF) {
- var waitQueue = [];
-
- function waitForTick(fn) {
- waitQueue.push(fn);
- if (waitQueue.length > 1) return;
- $$rAF(function() {
- for (var i = 0; i < waitQueue.length; i++) {
- waitQueue[i]();
- }
- waitQueue = [];
- });
- }
-
- return function() {
- var passed = false;
- waitForTick(function() {
- passed = true;
- });
- return function(callback) {
- passed ? callback() : waitForTick(callback);
- };
- };
- }];
-};
-
-var $$AnimateRunnerFactoryProvider = function() {
- this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout',
- function($q, $sniffer, $$animateAsyncRun, $document, $timeout) {
-
- var INITIAL_STATE = 0;
- var DONE_PENDING_STATE = 1;
- var DONE_COMPLETE_STATE = 2;
-
- AnimateRunner.chain = function(chain, callback) {
- var index = 0;
-
- next();
- function next() {
- if (index === chain.length) {
- callback(true);
- return;
- }
-
- chain[index](function(response) {
- if (response === false) {
- callback(false);
- return;
- }
- index++;
- next();
- });
- }
- };
-
- AnimateRunner.all = function(runners, callback) {
- var count = 0;
- var status = true;
- forEach(runners, function(runner) {
- runner.done(onProgress);
- });
-
- function onProgress(response) {
- status = status && response;
- if (++count === runners.length) {
- callback(status);
- }
- }
- };
-
- function AnimateRunner(host) {
- this.setHost(host);
-
- var rafTick = $$animateAsyncRun();
- var timeoutTick = function(fn) {
- $timeout(fn, 0, false);
- };
-
- this._doneCallbacks = [];
- this._tick = function(fn) {
- var doc = $document[0];
-
- // the document may not be ready or attached
- // to the module for some internal tests
- if (doc && doc.hidden) {
- timeoutTick(fn);
- } else {
- rafTick(fn);
- }
- };
- this._state = 0;
- }
-
- AnimateRunner.prototype = {
- setHost: function(host) {
- this.host = host || {};
- },
-
- done: function(fn) {
- if (this._state === DONE_COMPLETE_STATE) {
- fn();
- } else {
- this._doneCallbacks.push(fn);
- }
- },
-
- progress: noop,
-
- getPromise: function() {
- if (!this.promise) {
- var self = this;
- this.promise = $q(function(resolve, reject) {
- self.done(function(status) {
- status === false ? reject() : resolve();
- });
- });
- }
- return this.promise;
- },
-
- then: function(resolveHandler, rejectHandler) {
- return this.getPromise().then(resolveHandler, rejectHandler);
- },
-
- 'catch': function(handler) {
- return this.getPromise()['catch'](handler);
- },
-
- 'finally': function(handler) {
- return this.getPromise()['finally'](handler);
- },
-
- pause: function() {
- if (this.host.pause) {
- this.host.pause();
- }
- },
-
- resume: function() {
- if (this.host.resume) {
- this.host.resume();
- }
- },
-
- end: function() {
- if (this.host.end) {
- this.host.end();
- }
- this._resolve(true);
- },
-
- cancel: function() {
- if (this.host.cancel) {
- this.host.cancel();
- }
- this._resolve(false);
- },
-
- complete: function(response) {
- var self = this;
- if (self._state === INITIAL_STATE) {
- self._state = DONE_PENDING_STATE;
- self._tick(function() {
- self._resolve(response);
- });
- }
- },
-
- _resolve: function(response) {
- if (this._state !== DONE_COMPLETE_STATE) {
- forEach(this._doneCallbacks, function(fn) {
- fn(response);
- });
- this._doneCallbacks.length = 0;
- this._state = DONE_COMPLETE_STATE;
- }
- }
- };
-
- return AnimateRunner;
- }];
-};
-
-/**
- * @ngdoc service
- * @name $animateCss
- * @kind object
- *
- * @description
- * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
- * then the `$animateCss` service will actually perform animations.
- *
- * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
- */
-var $CoreAnimateCssProvider = function() {
- this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {
-
- return function(element, initialOptions) {
- // all of the animation functions should create
- // a copy of the options data, however, if a
- // parent service has already created a copy then
- // we should stick to using that
- var options = initialOptions || {};
- if (!options.$$prepared) {
- options = copy(options);
- }
-
- // there is no point in applying the styles since
- // there is no animation that goes on at all in
- // this version of $animateCss.
- if (options.cleanupStyles) {
- options.from = options.to = null;
- }
-
- if (options.from) {
- element.css(options.from);
- options.from = null;
- }
-
- /* jshint newcap: false */
- var closed, runner = new $$AnimateRunner();
- return {
- start: run,
- end: run
- };
-
- function run() {
- $$rAF(function() {
- applyAnimationContents();
- if (!closed) {
- runner.complete();
- }
- closed = true;
- });
- return runner;
- }
-
- function applyAnimationContents() {
- if (options.addClass) {
- element.addClass(options.addClass);
- options.addClass = null;
- }
- if (options.removeClass) {
- element.removeClass(options.removeClass);
- options.removeClass = null;
- }
- if (options.to) {
- element.css(options.to);
- options.to = null;
- }
- }
- };
- }];
-};
-
-/* global stripHash: true */
-
/**
* ! This is a private undocumented service !
*
- * @name $browser
+ * @name ng.$browser
* @requires $log
* @description
* This object has two goals:
@@ -5795,11 +4080,13 @@ var $CoreAnimateCssProvider = function() {
/**
* @param {object} window The global window object.
* @param {object} document jQuery wrapped document.
- * @param {object} $log window.console or an object with the same interface.
+ * @param {function()} XHR XMLHttpRequest constructor.
+ * @param {object} $log console.log or an object with the same interface.
* @param {object} $sniffer $sniffer service
*/
function Browser(window, document, $log, $sniffer) {
var self = this,
+ rawDocument = document[0],
location = window.location,
history = window.history,
setTimeout = window.setTimeout,
@@ -5825,7 +4112,7 @@ function Browser(window, document, $log, $sniffer) {
} finally {
outstandingRequestCount--;
if (outstandingRequestCount === 0) {
- while (outstandingRequestCallbacks.length) {
+ while(outstandingRequestCallbacks.length) {
try {
outstandingRequestCallbacks.pop()();
} catch (e) {
@@ -5836,11 +4123,6 @@ function Browser(window, document, $log, $sniffer) {
}
}
- function getHash(url) {
- var index = url.indexOf('#');
- return index === -1 ? '' : url.substr(index);
- }
-
/**
* @private
* Note: this method is used only by scenario runner
@@ -5848,6 +4130,11 @@ function Browser(window, document, $log, $sniffer) {
* @param {function()} callback Function that will be called when no outstanding request
*/
self.notifyWhenNoOutstandingRequests = function(callback) {
+ // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
+ // at some deterministic time in respect to the test runner's actions. Leaving things up to the
+ // regular poller would result in flaky tests.
+ forEach(pollFns, function(pollFn){ pollFn(); });
+
if (outstandingRequestCount === 0) {
callback();
} else {
@@ -5855,27 +4142,56 @@ function Browser(window, document, $log, $sniffer) {
}
};
+ //////////////////////////////////////////////////////////////
+ // Poll Watcher API
+ //////////////////////////////////////////////////////////////
+ var pollFns = [],
+ pollTimeout;
+
+ /**
+ * @name ng.$browser#addPollFn
+ * @methodOf ng.$browser
+ *
+ * @param {function()} fn Poll function to add
+ *
+ * @description
+ * Adds a function to the list of functions that poller periodically executes,
+ * and starts polling if not started yet.
+ *
+ * @returns {function()} the added function
+ */
+ self.addPollFn = function(fn) {
+ if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
+ pollFns.push(fn);
+ return fn;
+ };
+
+ /**
+ * @param {number} interval How often should browser call poll functions (ms)
+ * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
+ *
+ * @description
+ * Configures the poller to run in the specified intervals, using the specified
+ * setTimeout fn and kicks it off.
+ */
+ function startPoller(interval, setTimeout) {
+ (function check() {
+ forEach(pollFns, function(pollFn){ pollFn(); });
+ pollTimeout = setTimeout(check, interval);
+ })();
+ }
+
//////////////////////////////////////////////////////////////
// URL API
//////////////////////////////////////////////////////////////
- var cachedState, lastHistoryState,
- lastBrowserUrl = location.href,
+ var lastBrowserUrl = location.href,
baseElement = document.find('base'),
- pendingLocation = null,
- getCurrentState = !$sniffer.history ? noop : function getCurrentState() {
- try {
- return history.state;
- } catch (e) {
- // MSIE can reportedly throw when there is no state (UNCONFIRMED).
- }
- };
-
- cacheState();
- lastHistoryState = cachedState;
+ newLocation = null;
/**
- * @name $browser#url
+ * @name ng.$browser#url
+ * @methodOf ng.$browser
*
* @description
* GETTER:
@@ -5891,120 +4207,59 @@ function Browser(window, document, $log, $sniffer) {
* {@link ng.$location $location service} to change url.
*
* @param {string} url New url (when used as setter)
- * @param {boolean=} replace Should new url replace current history record?
- * @param {object=} state object to use with pushState/replaceState
+ * @param {boolean=} replace Should new url replace current history record ?
*/
- self.url = function(url, replace, state) {
- // In modern browsers `history.state` is `null` by default; treating it separately
- // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
- // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
- if (isUndefined(state)) {
- state = null;
- }
-
+ self.url = function(url, replace) {
// Android Browser BFCache causes location, history reference to become stale.
if (location !== window.location) location = window.location;
if (history !== window.history) history = window.history;
// setter
if (url) {
- var sameState = lastHistoryState === state;
-
- // Don't change anything if previous and current URLs and states match. This also prevents
- // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
- // See https://github.com/angular/angular.js/commit/ffb2701
- if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
- return self;
- }
- var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
+ if (lastBrowserUrl == url) return;
lastBrowserUrl = url;
- lastHistoryState = state;
- // Don't use history API if only the hash changed
- // due to a bug in IE10/IE11 which leads
- // to not firing a `hashchange` nor `popstate` event
- // in some cases (see #9143).
- if ($sniffer.history && (!sameBase || !sameState)) {
- history[replace ? 'replaceState' : 'pushState'](state, '', url);
- cacheState();
- // Do the assignment again so that those two variables are referentially identical.
- lastHistoryState = cachedState;
- } else {
- if (!sameBase || pendingLocation) {
- pendingLocation = url;
+ if ($sniffer.history) {
+ if (replace) history.replaceState(null, '', url);
+ else {
+ history.pushState(null, '', url);
+ // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462
+ baseElement.attr('href', baseElement.attr('href'));
}
+ } else {
+ newLocation = url;
if (replace) {
location.replace(url);
- } else if (!sameBase) {
- location.href = url;
} else {
- location.hash = getHash(url);
- }
- if (location.href !== url) {
- pendingLocation = url;
+ location.href = url;
}
}
return self;
// getter
} else {
- // - pendingLocation is needed as browsers don't allow to read out
- // the new location.href if a reload happened or if there is a bug like in iOS 9 (see
- // https://openradar.appspot.com/22186109).
+ // - newLocation is a workaround for an IE7-9 issue with location.replace and location.href
+ // methods not updating location.href synchronously.
// - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
- return pendingLocation || location.href.replace(/%27/g,"'");
+ return newLocation || location.href.replace(/%27/g,"'");
}
};
- /**
- * @name $browser#state
- *
- * @description
- * This method is a getter.
- *
- * Return history.state or null if history.state is undefined.
- *
- * @returns {object} state
- */
- self.state = function() {
- return cachedState;
- };
-
var urlChangeListeners = [],
urlChangeInit = false;
- function cacheStateAndFireUrlChange() {
- pendingLocation = null;
- cacheState();
- fireUrlChange();
- }
-
- // This variable should be used *only* inside the cacheState function.
- var lastCachedState = null;
- function cacheState() {
- // This should be the only place in $browser where `history.state` is read.
- cachedState = getCurrentState();
- cachedState = isUndefined(cachedState) ? null : cachedState;
-
- // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
- if (equals(cachedState, lastCachedState)) {
- cachedState = lastCachedState;
- }
- lastCachedState = cachedState;
- }
-
function fireUrlChange() {
- if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
- return;
- }
+ newLocation = null;
+ if (lastBrowserUrl == self.url()) return;
lastBrowserUrl = self.url();
- lastHistoryState = cachedState;
forEach(urlChangeListeners, function(listener) {
- listener(self.url(), cachedState);
+ listener(self.url());
});
}
/**
- * @name $browser#onUrlChange
+ * @name ng.$browser#onUrlChange
+ * @methodOf ng.$browser
+ * @TODO(vojta): refactor to use node's syntax for events
*
* @description
* Register callback function that will be called, when url changes.
@@ -6025,16 +4280,17 @@ function Browser(window, document, $log, $sniffer) {
* @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
*/
self.onUrlChange = function(callback) {
- // TODO(vojta): refactor to use node's syntax for events
if (!urlChangeInit) {
// We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
// don't fire popstate when user change the address bar and don't fire hashchange when url
// changed by push/replaceState
// html5 history api - popstate event
- if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
+ if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
// hashchange event
- jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
+ if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
+ // polling
+ else self.addPollFn(fireUrlChange);
urlChangeInit = true;
}
@@ -6043,43 +4299,105 @@ function Browser(window, document, $log, $sniffer) {
return callback;
};
- /**
- * @private
- * Remove popstate and hashchange handler from window.
- *
- * NOTE: this api is intended for use only by $rootScope.
- */
- self.$$applicationDestroyed = function() {
- jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);
- };
-
- /**
- * Checks whether the url has changed outside of Angular.
- * Needs to be exported to be able to check for changes that have been done in sync,
- * as hashchange/popstate events fire in async.
- */
- self.$$checkUrlChange = fireUrlChange;
-
//////////////////////////////////////////////////////////////
// Misc API
//////////////////////////////////////////////////////////////
/**
- * @name $browser#baseHref
+ * @name ng.$browser#baseHref
+ * @methodOf ng.$browser
*
* @description
* Returns current
+ *
* var cache = $cacheFactory('cacheId');
* expect($cacheFactory.get('cacheId')).toBe(cache);
* expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
@@ -6151,9 +4469,9 @@ function $BrowserProvider() {
* cache.put("another key", "another value");
*
* // We've specified no options on creation
- * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
- *
- * ```
+ * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
+ *
+ *
*
*
* @param {string} cacheId Name or id of the newly created cache.
@@ -6171,48 +4489,6 @@ function $BrowserProvider() {
* - `{void}` `removeAll()` — Removes all cached values.
* - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
*
- * @example
- Cached Values
-Cache Info
-+ * + * + * + * + * ... + * + *+ * * **Note:** the `script` tag containing the template does not need to be included in the `head` of - * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, - * element with ng-app attribute), otherwise the template will be ignored. - * - * Adding via the `$templateCache` service: - * - * ```js + * the document, but it must be below the `ng-app` definition. + * + * Adding via the $templateCache service: + * + *
* var myApp = angular.module('myApp', []);
* myApp.run(function($templateCache) {
* $templateCache.put('templateId.html', 'This is the content of the template');
* });
- * ```
- *
+ *
+ *
* To retrieve the template later, simply use it in your HTML:
- * ```html
+ * * - * ``` - * + *+ * * or get it via Javascript: - * ```js + *
* $templateCache.get('templateId.html')
- * ```
- *
+ *
+ *
* See {@link ng.$cacheFactory $cacheFactory}.
*
*/
@@ -6535,17 +4697,6 @@ function $TemplateCacheProvider() {
}];
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Any commits to this file should be reviewed with security in mind. *
- * Changes to this file can potentially create security vulnerabilities. *
- * An approval from 2 Core members with history of modifying *
- * this file is required. *
- * *
- * Does the change somehow allow for arbitrary javascript to be executed? *
- * Or allows for someone to change the prototype of built-in objects? *
- * Or gives undesired access to variables likes document or window? *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
*
* DOM-related variables:
@@ -6565,16 +4716,16 @@ function $TemplateCacheProvider() {
/**
- * @ngdoc service
- * @name $compile
- * @kind function
+ * @ngdoc function
+ * @name ng.$compile
+ * @function
*
* @description
* Compiles an HTML string or DOM into a template and produces a template function, which
* can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
*
* The compilation is a process of walking the DOM tree and matching DOM elements to
- * {@link ng.$compileProvider#directive directives}.
+ * {@link ng.$compileProvider#methods_directive directives}.
*
*
* var myModule = angular.module(...);
*
* myModule.directive('directiveName', function factory(injectables) {
@@ -6605,13 +4756,11 @@ function $TemplateCacheProvider() {
* template: '', // or // function(tElement, tAttrs) { ... },
* // or
* // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
+ * replace: false,
* transclude: false,
* restrict: 'A',
- * templateNamespace: 'html',
* scope: false,
* controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
- * controllerAs: 'stringIdentifier',
- * bindToController: false,
* require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
* compile: function compile(tElement, tAttrs, transclude) {
* return {
@@ -6631,7 +4780,7 @@ function $TemplateCacheProvider() {
* };
* return directiveDefinitionObject;
* });
- * ```
+ *
*
*
* var myModule = angular.module(...);
*
* myModule.directive('directiveName', function factory(injectables) {
@@ -6650,22 +4799,15 @@ function $TemplateCacheProvider() {
* // or
* // return function postLink(scope, iElement, iAttrs) { ... }
* });
- * ```
+ *
*
*
*
* ### Directive Definition Object
*
- * The directive definition object provides instructions to the {@link ng.$compile
+ * The directive definition object provides instructions to the {@link api/ng.$compile
* compiler}. The attributes are:
*
- * #### `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 recommended that this feature be used on directives
- * which are not strictly behavioral (such as {@link ngClick}), and which
- * do not manipulate or replace child nodes (such as {@link ngInclude}).
- *
* #### `priority`
* When there are multiple directives defined on a single DOM element, sometimes it
* is necessary to specify the order in which the directives are applied. The `priority` is used
@@ -6677,294 +4819,150 @@ function $TemplateCacheProvider() {
* #### `terminal`
* If set to true then the current `priority` will be the last set of directives
* which will execute (any directives at the current priority will still execute
- * as the order of execution on same `priority` is undefined). Note that expressions
- * and other directives used in the directive's template will also be excluded from execution.
+ * as the order of execution on same `priority` is undefined).
*
* #### `scope`
- * The scope property can be `true`, an object or a falsy value:
+ * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
+ * same element request a new scope, only one new scope is created. The new scope rule does not
+ * apply for the root of the template since the root of the template always gets a new scope.
*
- * * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
+ * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
+ * normal scope in that it does not prototypically inherit from the parent scope. This is useful
+ * when creating reusable components, which should not accidentally read or modify data in the
+ * parent scope.
*
- * * **`true`:** A new child scope that prototypically inherits from its parent will be created for
- * the directive's element. If multiple directives on the same element request a new scope,
- * only one new scope is created. The new scope rule does not apply for the root of the template
- * since the root of the template always gets a new scope.
- *
- * * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
- * 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
- * scope. This is useful when creating reusable components, which should not accidentally read or modify
- * data in the parent scope.
- *
- * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
- * directive's element. These local properties are useful for aliasing values for templates. The keys in
- * the object hash map to the name of the property on the isolate scope; the values define how the property
- * is bound to the parent scope, via matching attributes on the directive's element:
+ * The 'isolate' scope takes an object hash which defines a set of local scope properties
+ * derived from the parent scope. These local properties are useful for aliasing values for
+ * templates. Locals definition is a hash of local scope property to its source:
*
* * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
- * always a string since DOM attributes are strings. If no `attr` name is specified then the
- * attribute name is assumed to be the same as the local name. Given `
* function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
- * ```
+ *
*
* The link function is responsible for registering DOM listeners as well as updating the DOM. It is
* executed after the template has been cloned. This is where most of the directive logic will be
* put.
*
- * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
- * directive for registering {@link ng.$rootScope.Scope#$watch watches}.
+ * * `scope` - {@link api/ng.$rootScope.Scope Scope} - The scope to be used by the
+ * directive for registering {@link api/ng.$rootScope.Scope#methods_$watch watches}.
*
* * `iElement` - instance element - The element where the directive is to be used. It is safe to
* manipulate the children of the element only in `postLink` function since the children have
@@ -7028,23 +5016,15 @@ function $TemplateCacheProvider() {
* * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
* between all directive linking functions.
*
- * * `controller` - the directive's required controller instance(s) - Instances are shared
- * among all directives, which allows the directives to use the controllers as a communication
- * channel. The exact value depends on the directive's `require` property:
- * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one
- * * `string`: the controller instance
- * * `array`: array of controller instances
- *
- * If a required controller cannot be found, and it is optional, the instance is `null`,
- * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
- *
- * Note that you can also require the directive's own controller - it will be made available like
- * any other controller.
+ * * `controller` - a controller instance - A controller instance if at least one directive on the
+ * element defines a controller. The controller is shared among all the directives, which allows
+ * the directives to use the controllers as a communication channel.
*
* * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
- * This is the same as the `$transclude`
- * parameter of directive controllers, see there for details.
- * `function([scope], cloneLinkingFn, futureParentElement)`.
+ * The scope can be overridden by an optional first argument. This is the same as the `$transclude`
+ * parameter of directive controllers.
+ * `function([scope], cloneLinkingFn)`.
+ *
*
* #### Pre-linking function
*
@@ -7053,166 +5033,18 @@ function $TemplateCacheProvider() {
*
* #### 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.
- *
- *
- * ### Transclusion
- *
- * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
- * copying them to another part of the DOM, while maintaining their connection to the original AngularJS
- * scope from where they were taken.
- *
- * Transclusion is used (often with {@link ngTransclude}) to insert the
- * original contents of a directive's element into a specified place in the template of the directive.
- * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded
- * content has access to the properties on the scope from which it was taken, even if the directive
- * has isolated scope.
- * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.
- *
- * This makes it possible for the widget to have private state for its template, while the transcluded
- * content has access to its originating scope.
- *
- *
* function linkingFn(scope, elm, attrs, ctrl) {
* // get the attribute value
* console.log(attrs.ngModel);
@@ -7239,19 +5071,19 @@ function $TemplateCacheProvider() {
* console.log('ngModel has changed value to ' + value);
* });
* }
- * ```
+ *
*
- * ## Example
+ * Below is an example using `$compileProvider`.
*
*
* var element = $compile('{{total}}
')(scope);
- * ```
+ *
*
* - if on the other hand, you need the element to be cloned, the view reference from the original
* example would not point to the clone, but rather to the original template that was cloned. In
* this case, you can access the clone via the cloneAttachFn:
- * ```js
+ *
* var templateElement = angular.element('{{total}}
'),
* scope = ....;
*
@@ -7372,7 +5174,7 @@ function $TemplateCacheProvider() {
* });
*
* //now we have reference to the cloned DOM via `clonedElement`
- * ```
+ *
*
*
* For information on how the compiler works, see the
@@ -7382,8 +5184,9 @@ function $TemplateCacheProvider() {
var $compileMinErr = minErr('$compile');
/**
- * @ngdoc provider
- * @name $compileProvider
+ * @ngdoc service
+ * @name ng.$compileProvider
+ * @function
*
* @description
*/
@@ -7391,105 +5194,19 @@ $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
function $CompileProvider($provide, $$sanitizeUriProvider) {
var hasDirectives = {},
Suffix = 'Directive',
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
- CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
- ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
- REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
+ CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
// The assumption is that future DOM event attribute names will begin with
// 'on' and be composed of only English letters.
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
- var bindingCache = createMap();
-
- function parseIsolateBindings(scope, directiveName, isController) {
- var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/;
-
- var bindings = {};
-
- forEach(scope, function(definition, scopeName) {
- if (definition in bindingCache) {
- bindings[scopeName] = bindingCache[definition];
- return;
- }
- var match = definition.match(LOCAL_REGEXP);
-
- if (!match) {
- throw $compileMinErr('iscp',
- "Invalid {3} for directive '{0}'." +
- " Definition: {... {1}: '{2}' ...}",
- directiveName, scopeName, definition,
- (isController ? "controller bindings definition" :
- "isolate scope definition"));
- }
-
- bindings[scopeName] = {
- mode: match[1][0],
- collection: match[2] === '*',
- optional: match[3] === '?',
- attrName: match[4] || scopeName
- };
- if (match[4]) {
- bindingCache[definition] = bindings[scopeName];
- }
- });
-
- return bindings;
- }
-
- function parseDirectiveBindings(directive, directiveName) {
- var bindings = {
- isolateScope: null,
- bindToController: null
- };
- if (isObject(directive.scope)) {
- if (directive.bindToController === true) {
- bindings.bindToController = parseIsolateBindings(directive.scope,
- directiveName, true);
- bindings.isolateScope = {};
- } else {
- bindings.isolateScope = parseIsolateBindings(directive.scope,
- directiveName, false);
- }
- }
- if (isObject(directive.bindToController)) {
- bindings.bindToController =
- parseIsolateBindings(directive.bindToController, directiveName, true);
- }
- if (isObject(bindings.bindToController)) {
- var controller = directive.controller;
- var controllerAs = directive.controllerAs;
- if (!controller) {
- // There is no controller, there may or may not be a controllerAs property
- throw $compileMinErr('noctrl',
- "Cannot bind to controller without directive '{0}'s controller.",
- directiveName);
- } else if (!identifierForController(controller, controllerAs)) {
- // There is a controller, but no identifier or controllerAs property
- throw $compileMinErr('noident',
- "Cannot bind to controller without identifier for directive '{0}'.",
- directiveName);
- }
- }
- return bindings;
- }
-
- function assertValidDirectiveName(name) {
- var letter = name.charAt(0);
- if (!letter || letter !== lowercase(letter)) {
- throw $compileMinErr('baddir', "Directive/Component name '{0}' is invalid. The first character must be a lowercase letter", name);
- }
- if (name !== name.trim()) {
- throw $compileMinErr('baddir',
- "Directive/Component name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
- name);
- }
- }
/**
- * @ngdoc method
- * @name $compileProvider#directive
- * @kind function
+ * @ngdoc function
+ * @name ng.$compileProvider#directive
+ * @methodOf ng.$compileProvider
+ * @function
*
* @description
* Register a new directive with the compiler.
@@ -7497,14 +5214,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which
* will match as ng-bind), or an object map of directives where the keys are the
* names and the values are the factories.
- * @param {Function|Array} directiveFactory An injectable directive factory function. See the
- * {@link guide/directive directive guide} and the {@link $compile compile API} for more info.
+ * @param {function|Array} directiveFactory An injectable directive factory function. See
+ * {@link guide/directive} for more info.
* @returns {ng.$compileProvider} Self for chaining.
*/
- this.directive = function registerDirective(name, directiveFactory) {
+ this.directive = function registerDirective(name, directiveFactory) {
assertNotHasOwnProperty(name, 'directive');
if (isString(name)) {
- assertValidDirectiveName(name);
assertArg(directiveFactory, 'directiveFactory');
if (!hasDirectives.hasOwnProperty(name)) {
hasDirectives[name] = [];
@@ -7523,8 +5239,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
directive.index = index;
directive.name = directive.name || name;
directive.require = directive.require || (directive.controller && directive.name);
- directive.restrict = directive.restrict || 'EA';
- directive.$$moduleName = directiveFactory.$$moduleName;
+ directive.restrict = directive.restrict || 'A';
directives.push(directive);
} catch (e) {
$exceptionHandler(e);
@@ -7540,142 +5255,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return this;
};
- /**
- * @ngdoc method
- * @name $compileProvider#component
- * @module ng
- * @param {string} name Name of the component in camelCase (i.e. `myComp` which will match `$document title:
-window.document title:
-
+ * angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
+ * return function (exception, cause) {
* exception.message += ' (caused by "' + cause + '")';
* throw exception;
* };
* });
- * ```
- *
+ *
+ *
* This example will override the normal action of `$exceptionHandler`, to make angular
* exceptions fail hard when they happen, instead of just logging to the console.
*
- *
+ * $http({method: 'GET', url: '/someUrl'}).
+ * success(function(data, status, headers, config) {
* // this callback will be called asynchronously
* // when the response is available
- * }, function errorCallback(response) {
+ * }).
+ * error(function(data, status, headers, config) {
* // called asynchronously if an error occurs
* // or server returns response with an error status.
* });
- * ```
+ *
*
- * The response object has these properties:
- *
- * - **data** – `{string|Object}` – The response body transformed with the transform
- * functions.
- * - **status** – `{number}` – HTTP status code of the response.
- * - **headers** – `{function([headerName])}` – Header getter function.
- * - **config** – `{Object}` – The configuration object that was used to generate the request.
- * - **statusText** – `{string}` – HTTP status text of the response.
+ * Since the returned value of calling the $http function is a `promise`, you can also use
+ * the `then` method to register callbacks, and these callbacks will receive a single argument –
+ * an object representing the response. See the API signature and type info below for more
+ * details.
*
* A response status code between 200 and 299 is considered a success status and
* will result in the success callback being called. Note that if the response is a redirect,
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
* called for such responses.
*
+ * # Calling $http from outside AngularJS
+ * The `$http` service will not actually send the request until the next `$digest()` is
+ * executed. Normally this is not an issue, since almost all the time your call to `$http` will
+ * be from within a `$apply()` block.
+ * If you are calling `$http` from outside Angular, then you should wrap it in a call to
+ * `$apply` to cause a $digest to occur and also to handle errors in the block correctly.
*
- * ## 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. An optional config can be passed as the
- * last argument.
- *
- * ```js
- * $http.get('/someUrl', config).then(successCallback, errorCallback);
- * $http.post('/someUrl', data, config).then(successCallback, errorCallback);
+ * ```
+ * $scope.$apply(function() {
+ * $http(...);
+ * });
* ```
*
- * Complete list of shortcut methods:
- *
- * - {@link ng.$http#get $http.get}
- * - {@link ng.$http#head $http.head}
- * - {@link ng.$http#post $http.post}
- * - {@link ng.$http#put $http.put}
- * - {@link ng.$http#delete $http.delete}
- * - {@link ng.$http#jsonp $http.jsonp}
- * - {@link ng.$http#patch $http.patch}
- *
- *
- * ## 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.
+ * # Writing Unit Tests that use $http
+ * When unit testing you are mostly responsible for scheduling the `$digest` cycle. If you do
+ * not trigger a `$digest` before calling `$httpBackend.flush()` then the request will not have
+ * been made and `$httpBackend.expect(...)` expectations will fail. The solution is to run the
+ * code that calls the `$http()` method inside a $apply block as explained in the previous
+ * section.
*
* ```
* $httpBackend.expectGET(...);
- * $http.get(...);
+ * $scope.$apply(function() {
+ * $http.get(...);
+ * });
* $httpBackend.flush();
* ```
*
- * ## Deprecation Notice
- *
+ * $http.get('/someUrl').success(successCallback);
+ * $http.post('/someUrl', data).success(successCallback);
+ *
+ *
+ * Complete list of shortcut methods:
+ *
+ * - {@link ng.$http#methods_get $http.get}
+ * - {@link ng.$http#methods_head $http.head}
+ * - {@link ng.$http#methods_post $http.post}
+ * - {@link ng.$http#methods_put $http.put}
+ * - {@link ng.$http#methods_delete $http.delete}
+ * - {@link ng.$http#methods_jsonp $http.jsonp}
+ *
+ *
+ * # 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
@@ -10675,140 +7128,74 @@ function $HttpProvider() {
* To add or overwrite these defaults, simply add or remove a property from these configuration
* objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
* with the lowercased HTTP method name as the key, e.g.
- * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`.
+ * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.
*
* The defaults can also be set at runtime via the `$http.defaults` object in the same
* fashion. For example:
*
* ```
* module.run(function($http) {
- * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';
+ * $http.defaults.headers.common.Authentication = 'Basic YmVlcDpib29w'
* });
* ```
*
* In addition, you can supply a `headers` property in the config object passed when
* calling `$http(config)`, which overrides the defaults without changing them globally.
*
- * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
- * Use the `headers` property, setting the desired header to `undefined`. For example:
*
- * ```js
- * var req = {
- * method: 'POST',
- * url: 'http://example.com',
- * headers: {
- * 'Content-Type': undefined
- * },
- * data: { test: 'test' }
- * }
+ * # Transforming Requests and Responses
*
- * $http(req).then(function(){...}, function(){...});
- * ```
+ * Both requests and responses can be transformed using transform functions. By default, Angular
+ * applies these transformations:
*
- * ## 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, status)`) or an array of such transformation functions,
- * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
- *
- *
* // register the interceptor as a service
* $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
* return {
* // optional method
* 'request': function(config) {
* // do something on success
- * return config;
+ * return config || $q.when(config);
* },
*
* // optional method
@@ -10862,7 +7249,7 @@ function $HttpProvider() {
* // optional method
* 'response': function(response) {
* // do something on success
- * return response;
+ * return response || $q.when(response);
* },
*
* // optional method
@@ -10891,50 +7278,96 @@ function $HttpProvider() {
* }
* };
* });
- * ```
+ *
*
- * ## Security Considerations
+ * # Response interceptors (DEPRECATED)
+ *
+ * Before you start creating interceptors, be sure to understand the
+ * {@link ng.$q $q and deferred/promise APIs}.
+ *
+ * For purposes of global error handling, authentication or any kind of synchronous or
+ * asynchronous preprocessing of received responses, it is desirable to be able to intercept
+ * responses for http requests before they are handed over to the application code that
+ * initiated these requests. The response interceptors leverage the {@link ng.$q
+ * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.
+ *
+ * The interceptors are service factories that are registered with the $httpProvider by
+ * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and
+ * injected with dependencies (if specified) and returns the interceptor — a function that
+ * takes a {@link ng.$q promise} and returns the original or a new promise.
+ *
+ *
+ * // register the interceptor as a service
+ * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
+ * return function(promise) {
+ * return promise.then(function(response) {
+ * // do something on success
+ * return response;
+ * }, function(response) {
+ * // do something on error
+ * if (canRecover(response)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(response);
+ * });
+ * }
+ * });
+ *
+ * $httpProvider.responseInterceptors.push('myHttpInterceptor');
+ *
+ *
+ * // register the interceptor via an anonymous factory
+ * $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
+ * return function(promise) {
+ * // same as above
+ * }
+ * });
+ *
+ *
+ *
+ * # Security Considerations
*
* When designing web applications, consider security threats from:
*
- * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
- * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
+ * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
+ * JSON vulnerability}
+ * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}
*
* Both server and the client must cooperate in order to eliminate these threats. Angular comes
* 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
- * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
+ * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
+ * JSON vulnerability} allows third party website to turn your JSON resource URL into
+ * {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To
* counter this your server can prefix all JSON requests with following string `")]}',\n"`.
* Angular will automatically strip the prefix before processing it as JSON.
*
* For example if your server needs to return:
- * ```js
+ *
* ['one','two']
- * ```
+ *
*
* which is vulnerable to attack, your server can return:
- * ```js
+ *
* )]}',
* ['one','two']
- * ```
+ *
*
* 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 an attack technique by
- * which the attacker can trick an authenticated user into unknowingly executing actions on your
- * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the
- * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP
- * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the
- * cookie, your server can be assured that the XHR came from JavaScript running on your domain.
- * The header will not be set for cross-domain requests.
+ * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which
+ * an unauthorized site can gain your user's private data. Angular provides a mechanism
+ * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
+ * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
+ * JavaScript that runs on your domain could read the cookie, your server can be assured that
+ * the XHR came from JavaScript running on your domain. The header will not be set for
+ * cross-domain requests.
*
* To take advantage of this, your server needs to set a token in a JavaScript readable session
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
@@ -10942,85 +7375,84 @@ function $HttpProvider() {
* that only JavaScript running on your domain could have sent the request. The token must be
* unique for each user and must be verifiable by the server (to prevent the JavaScript from
* making up its own tokens). We recommend that the token is a digest of your site's
- * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
+ * authentication cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt}
* for added security.
*
* The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
* properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
* or the per-request config object.
*
- * In order to prevent collisions in environments where multiple Angular apps share the
- * same domain or subdomain, we recommend that each application uses unique cookie name.
*
* @param {object} config Object describing the request to be made and how it should be
* processed. The object has following properties:
*
* - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
* - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
- * - **params** – `{Object.