summaryrefslogtreecommitdiffstats
path: root/js/vendor/angular/angular.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/vendor/angular/angular.js')
-rw-r--r--js/vendor/angular/angular.js11013
1 files changed, 7495 insertions, 3518 deletions
diff --git a/js/vendor/angular/angular.js b/js/vendor/angular/angular.js
index 2445ab55e..a8aad46a8 100644
--- a/js/vendor/angular/angular.js
+++ b/js/vendor/angular/angular.js
@@ -1,6 +1,6 @@
/**
- * @license AngularJS v1.3.20
- * (c) 2010-2014 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.5.0
+ * (c) 2010-2016 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document, undefined) {'use strict';
@@ -38,28 +38,33 @@
function minErr(module, ErrorConstructor) {
ErrorConstructor = ErrorConstructor || Error;
return function() {
- var code = arguments[0],
- prefix = '[' + (module ? module + ':' : '') + code + '] ',
- template = arguments[1],
- templateArgs = arguments,
+ var SKIP_INDEXES = 2;
- 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 (index + 2 < templateArgs.length) {
- return toDebugString(templateArgs[index + 2]);
+ if (shiftedIndex < templateArgs.length) {
+ return toDebugString(templateArgs[shiftedIndex]);
}
+
return match;
});
- message = message + '\nhttp://errors.angularjs.org/1.3.20/' +
+ message += '\nhttp://errors.angularjs.org/1.5.0/' +
(module ? module + '/' : '') + code;
- for (i = 2; i < arguments.length; i++) {
- message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
- encodeURIComponent(toDebugString(arguments[i]));
+
+ for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
+ message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
+ encodeURIComponent(toDebugString(templateArgs[i]));
}
+
return new ErrorConstructor(message);
};
}
@@ -86,20 +91,21 @@ function minErr(module, ErrorConstructor) {
nodeName_: true,
isArrayLike: true,
forEach: true,
- sortedKeys: true,
forEachSorted: true,
reverseParams: true,
nextUid: true,
setHashKey: true,
extend: true,
- int: 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,
@@ -123,12 +129,15 @@ function minErr(module, ErrorConstructor) {
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,
@@ -179,29 +188,9 @@ var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
// This is used so that it's possible for internal tests to create mock ValidityStates.
var VALIDITY_STATE_PROPERTY = 'validity';
-/**
- * @ngdoc function
- * @name angular.lowercase
- * @module ng
- * @kind function
- *
- * @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 hasOwnProperty = Object.prototype.hasOwnProperty;
-/**
- * @ngdoc function
- * @name angular.uppercase
- * @module ng
- * @kind function
- *
- * @description Converts the specified string to uppercase.
- * @param {string} string String to be converted to uppercase.
- * @returns {string} Uppercased string.
- */
+var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
@@ -221,7 +210,7 @@ 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.
+// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387
if ('i' !== 'I'.toLowerCase()) {
lowercase = manualLowercase;
uppercase = manualUppercase;
@@ -236,6 +225,7 @@ var
splice = [].splice,
push = [].push,
toString = Object.prototype.toString,
+ getPrototypeOf = Object.getPrototypeOf,
ngMinErr = minErr('ng'),
/** @name angular */
@@ -257,20 +247,25 @@ 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;
+
+ // 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;
- if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
- return true;
- }
+ // 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');
- return isString(obj) || isArray(obj) || length === 0 ||
- typeof length === 'number' && length > 0 && (length - 1) in obj;
}
/**
@@ -328,23 +323,32 @@ function forEach(obj, iterator, context) {
}
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context, obj);
- } else {
+ } 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
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);
+ }
+ }
}
}
return obj;
}
-function sortedKeys(obj) {
- return Object.keys(obj).sort();
-}
-
function forEachSorted(obj, iterator, context) {
- var keys = sortedKeys(obj);
+ var keys = Object.keys(obj).sort();
for (var i = 0; i < keys.length; i++) {
iterator.call(context, obj[keys[i]], keys[i]);
}
@@ -358,7 +362,7 @@ 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);};
}
/**
@@ -389,6 +393,41 @@ function setHashKey(obj, h) {
}
}
+
+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
@@ -399,31 +438,44 @@ function setHashKey(obj, h) {
* 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).
+ *
+ * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
+ * {@link angular.merge} for this.
*
* @param {Object} dst Destination object.
* @param {...Object} src Source object(s).
* @returns {Object} Reference to `dst`.
*/
function extend(dst) {
- var h = dst.$$hashKey;
+ return baseExtend(dst, slice.call(arguments, 1), false);
+}
- for (var i = 1, ii = arguments.length; i < ii; i++) {
- var obj = arguments[i];
- if (obj) {
- var keys = Object.keys(obj);
- for (var j = 0, jj = keys.length; j < jj; j++) {
- var key = keys[j];
- dst[key] = obj[key];
- }
- }
- }
- setHashKey(dst, h);
- 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 int(str) {
+
+
+function toInt(str) {
return parseInt(str, 10);
}
@@ -476,6 +528,11 @@ identity.$inject = [];
function valueFn(value) {return function() {return value;};}
+function hasCustomToString(obj) {
+ return isFunction(obj.toString) && obj.toString !== toString;
+}
+
+
/**
* @ngdoc function
* @name angular.isUndefined
@@ -526,6 +583,16 @@ function isObject(value) {
/**
+ * 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);
+}
+
+
+/**
* @ngdoc function
* @name angular.isString
* @module ng
@@ -661,6 +728,16 @@ function isPromiseLike(obj) {
}
+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;
};
@@ -697,9 +774,10 @@ function isElement(node) {
* @returns {object} in the form of {key1:true, key2:true, ...}
*/
function makeMap(str) {
- var obj = {}, items = str.split(","), i;
- for (i = 0; i < items.length; i++)
+ var obj = {}, items = str.split(','), i;
+ for (i = 0; i < items.length; i++) {
obj[items[i]] = true;
+ }
return obj;
}
@@ -714,9 +792,10 @@ function includes(array, obj) {
function arrayRemove(array, value) {
var index = array.indexOf(value);
- if (index >= 0)
+ if (index >= 0) {
array.splice(index, 1);
- return value;
+ }
+ return index;
}
/**
@@ -777,77 +856,138 @@ function arrayRemove(array, value) {
</file>
</example>
*/
-function copy(source, destination, stackSource, stackDest) {
- if (isWindow(source) || isScope(source)) {
- throw ngMinErr('cpws',
- "Can't copy! Making copies of Window or Scope instances is not supported.");
- }
+function copy(source, destination) {
+ var stackSource = [];
+ var stackDest = [];
- if (!destination) {
- destination = source;
- if (source) {
- if (isArray(source)) {
- destination = copy(source, [], stackSource, stackDest);
- } else if (isDate(source)) {
- destination = new Date(source.getTime());
- } else if (isRegExp(source)) {
- destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
- destination.lastIndex = source.lastIndex;
- } else if (isObject(source)) {
- var emptyObject = Object.create(Object.getPrototypeOf(source));
- destination = copy(source, emptyObject, stackSource, stackDest);
- }
+ if (destination) {
+ if (isTypedArray(destination) || isArrayBuffer(destination)) {
+ throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
+ }
+ if (source === destination) {
+ throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
}
- } else {
- if (source === destination) throw ngMinErr('cpi',
- "Can't copy! Source and destination are identical.");
- stackSource = stackSource || [];
- stackDest = stackDest || [];
+ // Empty the destination object
+ if (isArray(destination)) {
+ destination.length = 0;
+ } else {
+ forEach(destination, function(value, key) {
+ if (key !== '$$hashKey') {
+ delete destination[key];
+ }
+ });
+ }
- if (isObject(source)) {
- var index = stackSource.indexOf(source);
- if (index !== -1) return stackDest[index];
+ stackSource.push(source);
+ stackDest.push(destination);
+ return copyRecurse(source, destination);
+ }
- stackSource.push(source);
- stackDest.push(destination);
- }
+ return copyElement(source);
- var result;
+ function copyRecurse(source, destination) {
+ var h = destination.$$hashKey;
+ var result, key;
if (isArray(source)) {
- destination.length = 0;
- for (var i = 0; i < source.length; i++) {
- result = copy(source[i], null, stackSource, stackDest);
- if (isObject(source[i])) {
- stackSource.push(source[i]);
- stackDest.push(result);
- }
- destination.push(result);
+ for (var i = 0, ii = source.length; i < ii; i++) {
+ destination.push(copyElement(source[i]));
}
- } else {
- var h = destination.$$hashKey;
- if (isArray(destination)) {
- destination.length = 0;
- } else {
- forEach(destination, function(value, key) {
- delete destination[key];
- });
+ } else if (isBlankObject(source)) {
+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
+ for (key in source) {
+ destination[key] = copyElement(source[key]);
}
- for (var key in source) {
+ } else if (source && typeof source.hasOwnProperty === 'function') {
+ // Slow path, which must rely on hasOwnProperty
+ for (key in source) {
if (source.hasOwnProperty(key)) {
- result = copy(source[key], null, stackSource, stackDest);
- if (isObject(source[key])) {
- stackSource.push(source[key]);
- stackDest.push(result);
- }
- destination[key] = result;
+ destination[key] = copyElement(source[key]);
}
}
- setHashKey(destination,h);
+ } else {
+ // Slowest path --- hasOwnProperty can't be called as a method
+ for (key in source) {
+ if (hasOwnProperty.call(source, key)) {
+ destination[key] = copyElement(source[key]);
+ }
+ }
+ }
+ setHashKey(destination, h);
+ return destination;
+ }
+
+ function copyElement(source) {
+ // Simple values
+ if (!isObject(source)) {
+ return source;
+ }
+
+ // Already copied values
+ var index = stackSource.indexOf(source);
+ if (index !== -1) {
+ return stackDest[index];
+ }
+
+ if (isWindow(source) || isScope(source)) {
+ throw ngMinErr('cpws',
+ "Can't copy! Making copies of Window or Scope instances is not supported.");
+ }
+
+ var needsRecurse = false;
+ var destination = copyType(source);
+
+ if (destination === undefined) {
+ destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
+ needsRecurse = true;
+ }
+
+ stackSource.push(source);
+ stackDest.push(destination);
+
+ return needsRecurse
+ ? copyRecurse(source, destination)
+ : destination;
+ }
+
+ function copyType(source) {
+ switch (toString.call(source)) {
+ case '[object Int8Array]':
+ case '[object Int16Array]':
+ case '[object Int32Array]':
+ case '[object Float32Array]':
+ case '[object Float64Array]':
+ case '[object Uint8Array]':
+ case '[object Uint8ClampedArray]':
+ case '[object Uint16Array]':
+ case '[object Uint32Array]':
+ return new source.constructor(copyElement(source.buffer));
+
+ case '[object ArrayBuffer]':
+ //Support: IE10
+ if (!source.slice) {
+ var copied = new ArrayBuffer(source.byteLength);
+ new Uint8Array(copied).set(new Uint8Array(source));
+ return copied;
+ }
+ return source.slice(0);
+
+ case '[object Boolean]':
+ case '[object Number]':
+ case '[object String]':
+ case '[object Date]':
+ return new source.constructor(source.valueOf());
+
+ case '[object RegExp]':
+ var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
+ re.lastIndex = source.lastIndex;
+ return re;
}
+ if (isFunction(source.cloneNode)) {
+ return source.cloneNode(true);
+ }
}
- return destination;
}
/**
@@ -910,63 +1050,130 @@ function equals(o1, o2) {
if (o1 === null || o2 === null) return false;
if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
- if (t1 == t2) {
- if (t1 == 'object') {
- if (isArray(o1)) {
- if (!isArray(o2)) return false;
- if ((length = o1.length) == o2.length) {
- for (key = 0; key < length; key++) {
- if (!equals(o1[key], o2[key])) return false;
- }
- return true;
- }
- } else if (isDate(o1)) {
- if (!isDate(o2)) return false;
- return equals(o1.getTime(), o2.getTime());
- } else if (isRegExp(o1)) {
- return isRegExp(o2) ? o1.toString() == o2.toString() : false;
- } else {
- if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
- isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
- keySet = {};
- for (key in o1) {
- if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+ if (t1 == t2 && t1 == 'object') {
+ if (isArray(o1)) {
+ if (!isArray(o2)) return false;
+ if ((length = o1.length) == o2.length) {
+ for (key = 0; key < length; key++) {
if (!equals(o1[key], o2[key])) return false;
- keySet[key] = true;
- }
- for (key in o2) {
- if (!keySet.hasOwnProperty(key) &&
- key.charAt(0) !== '$' &&
- o2[key] !== undefined &&
- !isFunction(o2[key])) return false;
}
return true;
}
+ } else if (isDate(o1)) {
+ if (!isDate(o2)) return false;
+ return equals(o1.getTime(), o2.getTime());
+ } else if (isRegExp(o1)) {
+ if (!isRegExp(o2)) return false;
+ return o1.toString() == o2.toString();
+ } else {
+ if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
+ isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
+ keySet = createMap();
+ for (key in o1) {
+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+ if (!equals(o1[key], o2[key])) return false;
+ keySet[key] = true;
+ }
+ for (key in o2) {
+ if (!(key in keySet) &&
+ key.charAt(0) !== '$' &&
+ isDefined(o2[key]) &&
+ !isFunction(o2[key])) return false;
+ }
+ return true;
}
}
return false;
}
var csp = function() {
- if (isDefined(csp.isActive_)) return csp.isActive_;
+ if (!isDefined(csp.rules)) {
+
+
+ var ngCspElement = (document.querySelector('[ng-csp]') ||
+ document.querySelector('[data-ng-csp]'));
+
+ if (ngCspElement) {
+ var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
+ ngCspElement.getAttribute('data-ng-csp');
+ csp.rules = {
+ noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),
+ noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)
+ };
+ } else {
+ csp.rules = {
+ noUnsafeEval: noUnsafeEval(),
+ noInlineStyle: false
+ };
+ }
+ }
- var active = !!(document.querySelector('[ng-csp]') ||
- document.querySelector('[data-ng-csp]'));
+ return csp.rules;
- if (!active) {
+ function noUnsafeEval() {
try {
/* jshint -W031, -W054 */
new Function('');
/* jshint +W031, +W054 */
+ return false;
} catch (e) {
- active = true;
+ return true;
}
}
-
- return (csp.isActive_ = active);
};
+/**
+ * @ngdoc directive
+ * @module ng
+ * @name ngJq
+ *
+ * @element ANY
+ * @param {string=} ngJq the name of the library available under `window`
+ * to be used for angular.element
+ * @description
+ * Use this directive to force the angular.element library. This should be
+ * used to force either jqLite by leaving ng-jq blank or setting the name of
+ * the jquery variable under window (eg. jQuery).
+ *
+ * Since angular looks for this directive when it is loaded (doesn't wait for the
+ * DOMContentLoaded event), it must be placed on an element that comes before the script
+ * which loads angular. Also, only the first instance of `ng-jq` will be used and all
+ * others ignored.
+ *
+ * @example
+ * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
+ ```html
+ <!doctype html>
+ <html ng-app ng-jq>
+ ...
+ ...
+ </html>
+ ```
+ * @example
+ * This example shows how to use a jQuery based library of a different name.
+ * The library name must be available at the top most 'window'.
+ ```html
+ <!doctype html>
+ <html ng-app ng-jq="jQueryLib">
+ ...
+ ...
+ </html>
+ ```
+ */
+var jq = function() {
+ if (isDefined(jq.name_)) return jq.name_;
+ var el;
+ var i, ii = ngAttrPrefixes.length, prefix, name;
+ for (i = 0; i < ii; ++i) {
+ prefix = ngAttrPrefixes[i];
+ if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
+ name = el.getAttribute(prefix + 'jq');
+ break;
+ }
+ }
+ return (jq.name_ = name);
+};
function concat(array1, array2, index) {
return array1.concat(slice.call(array2, index));
@@ -1050,7 +1257,7 @@ function toJsonReplacer(key, value) {
* @returns {string|undefined} JSON-ified string representing `obj`.
*/
function toJson(obj, pretty) {
- if (typeof obj === 'undefined') return undefined;
+ if (isUndefined(obj)) return undefined;
if (!isNumber(pretty)) {
pretty = pretty ? 2 : null;
}
@@ -1077,6 +1284,30 @@ function fromJson(json) {
}
+var ALL_COLONS = /:/g;
+function timezoneToOffset(timezone, fallback) {
+ // IE/Edge do not "understand" colon (`:`) in timezone
+ timezone = timezone.replace(ALL_COLONS, '');
+ var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
+ return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
+}
+
+
+function addDateMinutes(date, minutes) {
+ date = new Date(date.getTime());
+ date.setMinutes(date.getMinutes() + minutes);
+ return date;
+}
+
+
+function convertTimezoneToLocal(date, timezone, reverse) {
+ reverse = reverse ? -1 : 1;
+ var dateTimezoneOffset = date.getTimezoneOffset();
+ var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
+ return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
+}
+
+
/**
* @returns {string} Returns the string representation of the element.
*/
@@ -1092,7 +1323,7 @@ function startingTag(element) {
return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
elemHtml.
match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);});
} catch (e) {
return lowercase(elemHtml);
}
@@ -1124,13 +1355,19 @@ function tryDecodeURIComponent(value) {
* @returns {Object.<string,boolean|Array>}
*/
function parseKeyValue(/**string*/keyValue) {
- var obj = {}, key_value, key;
+ var obj = {};
forEach((keyValue || "").split('&'), function(keyValue) {
+ var splitPoint, key, val;
if (keyValue) {
- key_value = keyValue.replace(/\+/g,'%20').split('=');
- key = tryDecodeURIComponent(key_value[0]);
+ key = keyValue = keyValue.replace(/\+/g,'%20');
+ splitPoint = keyValue.indexOf('=');
+ if (splitPoint !== -1) {
+ key = keyValue.substring(0, splitPoint);
+ val = keyValue.substring(splitPoint + 1);
+ }
+ key = tryDecodeURIComponent(key);
if (isDefined(key)) {
- var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
+ val = isDefined(val) ? tryDecodeURIComponent(val) : true;
if (!hasOwnProperty.call(obj, key)) {
obj[key] = val;
} else if (isArray(obj[key])) {
@@ -1205,10 +1442,9 @@ var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
function getNgAttribute(element, ngAttr) {
var attr, i, ii = ngAttrPrefixes.length;
- element = jqLite(element);
for (i = 0; i < ii; ++i) {
attr = ngAttrPrefixes[i] + ngAttr;
- if (isString(attr = element.attr(attr))) {
+ if (isString(attr = element.getAttribute(attr))) {
return attr;
}
}
@@ -1530,7 +1766,6 @@ function snake_case(name, separator) {
}
var bindJQueryFired = false;
-var skipDestroyOnNextJQueryCleanData;
function bindJQuery() {
var originalCleanData;
@@ -1539,7 +1774,11 @@ function bindJQuery() {
}
// bind to jQuery if present;
- jQuery = window.jQuery;
+ var jqName = jq();
+ jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
+ !jqName ? undefined : // use jqLite
+ window[jqName]; // use jQuery specified by `ngJq`
+
// Use jQuery if it exists with proper functionality, otherwise default to us.
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
// Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
@@ -1560,15 +1799,11 @@ function bindJQuery() {
originalCleanData = jQuery.cleanData;
jQuery.cleanData = function(elems) {
var events;
- if (!skipDestroyOnNextJQueryCleanData) {
- for (var i = 0, elem; (elem = elems[i]) != null; i++) {
- events = jQuery._data(elem, "events");
- if (events && events.$destroy) {
- jQuery(elem).triggerHandler('$destroy');
- }
+ for (var i = 0, elem; (elem = elems[i]) != null; i++) {
+ events = jQuery._data(elem, "events");
+ if (events && events.$destroy) {
+ jQuery(elem).triggerHandler('$destroy');
}
- } else {
- skipDestroyOnNextJQueryCleanData = false;
}
originalCleanData(elems);
};
@@ -1643,22 +1878,24 @@ function getter(obj, path, bindFnToScope) {
/**
* Return the DOM siblings between the first and last node in the given array.
* @param {Array} array like object
- * @returns {jqLite} jqLite collection containing the nodes
+ * @returns {Array} the inputted object or a jqLite collection containing the nodes
*/
function getBlockNodes(nodes) {
- // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
- // collection, otherwise update the original collection.
+ // TODO(perf): update `nodes` instead of creating a new object?
var node = nodes[0];
var endNode = nodes[nodes.length - 1];
- var blockNodes = [node];
+ var blockNodes;
- do {
- node = node.nextSibling;
- if (!node) break;
- blockNodes.push(node);
- } while (node !== endNode);
+ for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
+ if (blockNodes || nodes[i] !== node) {
+ if (!blockNodes) {
+ blockNodes = jqLite(slice.call(nodes, 0, i));
+ }
+ blockNodes.push(node);
+ }
+ }
- return jqLite(blockNodes);
+ return blockNodes || nodes;
}
@@ -1722,8 +1959,8 @@ function setupModuleLoader(window) {
* All modules (angular core or 3rd party) that should be available to an application must be
* registered using this mechanism.
*
- * When passed two or more arguments, a new module is created. If passed only one argument, an
- * existing module (the name passed as the first argument to `module`) is retrieved.
+ * Passing one argument retrieves an existing {@link angular.Module},
+ * whereas passing more than one argument creates a new {@link angular.Module}
*
*
* # Module
@@ -1760,7 +1997,7 @@ function setupModuleLoader(window) {
* unspecified then the module is being retrieved for further configuration.
* @param {Function=} configFn Optional configuration function for the module. Same as
* {@link angular.Module#config Module#config()}.
- * @returns {module} new module with the {@link angular.Module} api.
+ * @returns {angular.Module} new module with the {@link angular.Module} api.
*/
return function module(name, requires, configFn) {
var assertNotHasOwnProperty = function(name, context) {
@@ -1830,7 +2067,7 @@ function setupModuleLoader(window) {
* @description
* See {@link auto.$provide#provider $provide.provider()}.
*/
- provider: invokeLater('$provide', 'provider'),
+ provider: invokeLaterAndSetModuleName('$provide', 'provider'),
/**
* @ngdoc method
@@ -1841,7 +2078,7 @@ function setupModuleLoader(window) {
* @description
* See {@link auto.$provide#factory $provide.factory()}.
*/
- factory: invokeLater('$provide', 'factory'),
+ factory: invokeLaterAndSetModuleName('$provide', 'factory'),
/**
* @ngdoc method
@@ -1852,7 +2089,7 @@ function setupModuleLoader(window) {
* @description
* See {@link auto.$provide#service $provide.service()}.
*/
- service: invokeLater('$provide', 'service'),
+ service: invokeLaterAndSetModuleName('$provide', 'service'),
/**
* @ngdoc method
@@ -1872,11 +2109,23 @@ function setupModuleLoader(window) {
* @param {string} name constant name
* @param {*} object Constant value.
* @description
- * Because the constant are fixed, they get applied before other provide methods.
+ * Because the constants are fixed, they get applied before other provide methods.
* See {@link auto.$provide#constant $provide.constant()}.
*/
constant: invokeLater('$provide', 'constant', 'unshift'),
+ /**
+ * @ngdoc method
+ * @name angular.Module#decorator
+ * @module ng
+ * @param {string} The name of the service to decorate.
+ * @param {Function} This function will be invoked when the service needs to be
+ * instantiated and should return the decorated service instance.
+ * @description
+ * See {@link auto.$provide#decorator $provide.decorator()}.
+ */
+ decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
+
/**
* @ngdoc method
* @name angular.Module#animation
@@ -1890,7 +2139,7 @@ function setupModuleLoader(window) {
*
*
* Defines an animation hook that can be later used with
- * {@link ngAnimate.$animate $animate} service and directives that use this service.
+ * {@link $animate $animate} service and directives that use this service.
*
* ```js