/files/angularjs/1.2.3/angular.js
JavaScript | 1705 lines | 696 code | 174 blank | 835 comment | 231 complexity | f7b8c2e188ed277185ed80601388bae2 MD5 | raw file
- /**
- * @license AngularJS v1.2.3
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
- (function(window, document, undefined) {'use strict';
- /**
- * @description
- *
- * This object provides a utility for producing rich Error messages within
- * Angular. It can be called as follows:
- *
- * var exampleMinErr = minErr('example');
- * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
- *
- * The above creates an instance of minErr in the example namespace. The
- * resulting error will have a namespaced error code of example.one. The
- * resulting error will replace {0} with the value of foo, and {1} with the
- * value of bar. The object is not restricted in the number of arguments it can
- * take.
- *
- * If fewer arguments are specified than necessary for interpolation, the extra
- * interpolation markers will be preserved in the final string.
- *
- * Since data will be parsed statically during a build step, some restrictions
- * are applied with respect to how minErr instances are created and called.
- * Instances should have names of the form namespaceMinErr for a minErr created
- * using minErr('namespace') . Error codes, namespaces and template strings
- * should all be static strings, not variables or general expressions.
- *
- * @param {string} module The namespace to use for the new minErr instance.
- * @returns {function(string, string, ...): Error} instance
- */
- 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;
- message = prefix + template.replace(/\{\d+\}/g, function (match) {
- var index = +match.slice(1, -1), arg;
- 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 = message + '\nhttp://errors.angularjs.org/1.2.3/' +
- (module ? module + '/' : '') + code;
- for (i = 2; i < arguments.length; i++) {
- message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
- encodeURIComponent(stringify(arguments[i]));
- }
- return new Error(message);
- };
- }
- /* We need to tell jshint what variables are being exported */
- /* global
- -angular,
- -msie,
- -jqLite,
- -jQuery,
- -slice,
- -push,
- -toString,
- -ngMinErr,
- -_angular,
- -angularModule,
- -nodeName_,
- -uid,
- -lowercase,
- -uppercase,
- -manualLowercase,
- -manualUppercase,
- -nodeName_,
- -isArrayLike,
- -forEach,
- -sortedKeys,
- -forEachSorted,
- -reverseParams,
- -nextUid,
- -setHashKey,
- -extend,
- -int,
- -inherit,
- -noop,
- -identity,
- -valueFn,
- -isUndefined,
- -isDefined,
- -isObject,
- -isString,
- -isNumber,
- -isDate,
- -isArray,
- -isFunction,
- -isRegExp,
- -isWindow,
- -isScope,
- -isFile,
- -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,
- */
- ////////////////////////////////////
- /**
- * @ngdoc function
- * @name angular.lowercase
- * @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;};
- /**
- * @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) {
- /* jshint bitwise: false */
- return isString(s)
- ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
- : s;
- };
- var manualUppercase = function(s) {
- /* jshint bitwise: false */
- return isString(s)
- ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
- : 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.
- if ('i' !== 'I'.toLowerCase()) {
- lowercase = manualLowercase;
- uppercase = manualUppercase;
- }
- 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,
- push = [].push,
- toString = Object.prototype.toString,
- ngMinErr = minErr('ng'),
- _angular = window.angular,
- /** @name angular */
- angular = window.angular || (window.angular = {}),
- angularModule,
- nodeName_,
- uid = ['0', '0', '0'];
- /**
- * IE 11 changed the format of the UserAgent string.
- * See http://msdn.microsoft.com/en-us/library/ms537503.aspx
- */
- msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
- if (isNaN(msie)) {
- msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
- }
- /**
- * @private
- * @param {*} obj
- * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
- * String ...)
- */
- function isArrayLike(obj) {
- if (obj == null || isWindow(obj)) {
- return false;
- }
- var length = obj.length;
- 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
- * @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)`, 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.
- *
- * Note: this function was previously known as `angular.foreach`.
- *
- <pre>
- var values = {name: 'misko', gender: 'male'};
- var log = [];
- angular.forEach(values, function(value, key){
- this.push(key + ': ' + value);
- }, log);
- expect(log).toEqual(['name: misko', 'gender:male']);
- </pre>
- *
- * @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;
- if (obj) {
- if (isFunction(obj)){
- for (key in obj) {
- if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
- iterator.call(context, obj[key], key);
- }
- }
- } else if (obj.forEach && obj.forEach !== forEach) {
- obj.forEach(iterator, context);
- } else if (isArrayLike(obj)) {
- for (key = 0; key < obj.length; key++)
- iterator.call(context, obj[key], key);
- } else {
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- iterator.call(context, obj[key], key);
- }
- }
- }
- }
- 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 = sortedKeys(obj);
- for ( var i = 0; i < keys.length; i++) {
- iterator.call(context, obj[keys[i]], keys[i]);
- }
- return keys;
- }
- /**
- * when using forEach the params are value, key, but it is often useful to have key, value.
- * @param {function(string, *)} iteratorFn
- * @returns {function(*, string)}
- */
- function reverseParams(iteratorFn) {
- return function(value, key) { iteratorFn(key, value); };
- }
- /**
- * 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.
- *
- * @returns an unique alpha-numeric string
- */
- function nextUid() {
- var index = uid.length;
- var digit;
- while(index) {
- index--;
- digit = uid[index].charCodeAt(0);
- if (digit == 57 /*'9'*/) {
- uid[index] = 'A';
- return uid.join('');
- }
- if (digit == 90 /*'Z'*/) {
- uid[index] = '0';
- } else {
- uid[index] = String.fromCharCode(digit + 1);
- return uid.join('');
- }
- }
- uid.unshift('0');
- return uid.join('');
- }
- /**
- * Set or clear the hashkey for an object.
- * @param obj object
- * @param h the hashkey (!truthy to delete the hashkey)
- */
- function setHashKey(obj, h) {
- if (h) {
- obj.$$hashKey = h;
- }
- else {
- delete obj.$$hashKey;
- }
- }
- /**
- * @ngdoc function
- * @name angular.extend
- * @function
- *
- * @description
- * 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) {
- var h = dst.$$hashKey;
- forEach(arguments, function(obj){
- if (obj !== dst) {
- forEach(obj, function(value, key){
- dst[key] = value;
- });
- }
- });
- setHashKey(dst,h);
- return dst;
- }
- function int(str) {
- return parseInt(str, 10);
- }
- function inherit(parent, extra) {
- return extend(new (extend(function() {}, {prototype:parent}))(), extra);
- }
- /**
- * @ngdoc function
- * @name angular.noop
- * @function
- *
- * @description
- * A function that performs no operations. This function can be useful when writing code in the
- * functional style.
- <pre>
- function foo(callback) {
- var result = calculateResult();
- (callback || angular.noop)(result);
- }
- </pre>
- */
- function noop() {}
- noop.$inject = [];
- /**
- * @ngdoc function
- * @name angular.identity
- * @function
- *
- * @description
- * A function that returns its first argument. This function is useful when writing code in the
- * functional style.
- *
- <pre>
- function transformer(transformationFn, value) {
- return (transformationFn || angular.identity)(value);
- };
- </pre>
- */
- function identity($) {return $;}
- identity.$inject = [];
- function valueFn(value) {return function() {return value;};}
- /**
- * @ngdoc function
- * @name angular.isUndefined
- * @function
- *
- * @description
- * Determines if a reference is undefined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is undefined.
- */
- function isUndefined(value){return typeof value == 'undefined';}
- /**
- * @ngdoc function
- * @name angular.isDefined
- * @function
- *
- * @description
- * Determines if a reference is defined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is defined.
- */
- function isDefined(value){return typeof value != 'undefined';}
- /**
- * @ngdoc function
- * @name angular.isObject
- * @function
- *
- * @description
- * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
- * considered to be objects.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Object` but not `null`.
- */
- function isObject(value){return value != null && typeof value == 'object';}
- /**
- * @ngdoc function
- * @name angular.isString
- * @function
- *
- * @description
- * Determines if a reference is a `String`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `String`.
- */
- function isString(value){return typeof value == 'string';}
- /**
- * @ngdoc function
- * @name angular.isNumber
- * @function
- *
- * @description
- * Determines if a reference is a `Number`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Number`.
- */
- function isNumber(value){return typeof value == 'number';}
- /**
- * @ngdoc function
- * @name angular.isDate
- * @function
- *
- * @description
- * Determines if a value is a date.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Date`.
- */
- function isDate(value){
- return toString.apply(value) == '[object Date]';
- }
- /**
- * @ngdoc function
- * @name angular.isArray
- * @function
- *
- * @description
- * Determines if a reference is an `Array`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Array`.
- */
- function isArray(value) {
- return toString.apply(value) == '[object Array]';
- }
- /**
- * @ngdoc function
- * @name angular.isFunction
- * @function
- *
- * @description
- * Determines if a reference is a `Function`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Function`.
- */
- function isFunction(value){return typeof value == 'function';}
- /**
- * Determines if a value is a regular expression object.
- *
- * @private
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `RegExp`.
- */
- function isRegExp(value) {
- return toString.apply(value) == '[object RegExp]';
- }
- /**
- * Checks if `obj` is a window object.
- *
- * @private
- * @param {*} obj Object to check
- * @returns {boolean} True if `obj` is a window obj.
- */
- function isWindow(obj) {
- return obj && obj.document && obj.location && obj.alert && obj.setInterval;
- }
- function isScope(obj) {
- return obj && obj.$evalAsync && obj.$watch;
- }
- function isFile(obj) {
- return toString.apply(obj) === '[object File]';
- }
- function isBoolean(value) {
- return typeof value == 'boolean';
- }
- var trim = (function() {
- // native trim is way faster: http://jsperf.com/angular-trim-test
- // but IE doesn't have it... :-(
- // TODO: we should move this into IE/ES5 polyfill
- if (!String.prototype.trim) {
- return function(value) {
- return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
- };
- }
- return function(value) {
- return isString(value) ? value.trim() : value;
- };
- })();
- /**
- * @ngdoc function
- * @name angular.isElement
- * @function
- *
- * @description
- * Determines if a reference is a DOM element (or wrapped jQuery element).
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
- */
- function isElement(node) {
- return node &&
- (node.nodeName // we are a direct element
- || (node.on && node.find)); // we have an on and find method part of jQuery API
- }
- /**
- * @param str 'key1,key2,...'
- * @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++ )
- obj[ items[i] ] = true;
- return obj;
- }
- if (msie < 9) {
- nodeName_ = function(element) {
- element = element.nodeName ? element : element[0];
- return (element.scopeName && element.scopeName != 'HTML')
- ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
- };
- } else {
- nodeName_ = function(element) {
- return element.nodeName ? element.nodeName : element[0].nodeName;
- };
- }
- function map(obj, iterator, context) {
- var results = [];
- forEach(obj, function(value, index, list) {
- results.push(iterator.call(context, value, index, list));
- });
- return results;
- }
- /**
- * @description
- * Determines the number of elements in an array, the number of properties an object has, or
- * the length of a string.
- *
- * Note: This function is used to augment the Object type in Angular expressions. See
- * {@link angular.Object} for more information about Angular arrays.
- *
- * @param {Object|Array|string} obj Object, array, or string to inspect.
- * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
- * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
- */
- function size(obj, ownPropsOnly) {
- var count = 0, key;
- if (isArray(obj) || isString(obj)) {
- return obj.length;
- } else if (isObject(obj)){
- for (key in obj)
- if (!ownPropsOnly || obj.hasOwnProperty(key))
- count++;
- }
- return count;
- }
- function includes(array, obj) {
- return indexOf(array, obj) != -1;
- }
- function indexOf(array, obj) {
- if (array.indexOf) return array.indexOf(obj);
- for ( var i = 0; i < array.length; i++) {
- if (obj === array[i]) return i;
- }
- return -1;
- }
- function arrayRemove(array, value) {
- 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 false;
- }
- /**
- * @ngdoc function
- * @name angular.copy
- * @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 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.
- *
- * @param {*} source The source that will be used to make a copy.
- * Can be any type, including primitives, `null`, and `undefined`.
- * @param {(Object|Array)=} destination Destination into which the source is copied. If
- * provided, must be of the same type as `source`.
- * @returns {*} The copy or updated `destination`, if `destination` was specified.
- *
- * @example
- <doc:example>
- <doc:source>
- <div ng-controller="Controller">
- <form novalidate class="simple-form">
- Name: <input type="text" ng-model="user.name" /><br />
- E-mail: <input type="email" ng-model="user.email" /><br />
- Gender: <input type="radio" ng-model="user.gender" value="male" />male
- <input type="radio" ng-model="user.gender" value="female" />female<br />
- <button ng-click="reset()">RESET</button>
- <button ng-click="update(user)">SAVE</button>
- </form>
- <pre>form = {{user | json}}</pre>
- <pre>master = {{master | json}}</pre>
- </div>
- <script>
- function Controller($scope) {
- $scope.master= {};
- $scope.update = function(user) {
- // Example with 1 argument
- $scope.master= angular.copy(user);
- };
- $scope.reset = function() {
- // Example with 2 arguments
- angular.copy($scope.master, $scope.user);
- };
- $scope.reset();
- }
- </script>
- </doc:source>
- </doc:example>
- */
- function copy(source, destination){
- if (isWindow(source) || isScope(source)) {
- throw ngMinErr('cpws',
- "Can't copy! Making copies of Window or Scope instances is not supported.");
- }
- if (!destination) {
- destination = source;
- if (source) {
- if (isArray(source)) {
- destination = copy(source, []);
- } else if (isDate(source)) {
- destination = new Date(source.getTime());
- } else if (isRegExp(source)) {
- destination = new RegExp(source.source);
- } else if (isObject(source)) {
- destination = copy(source, {});
- }
- }
- } else {
- if (source === destination) throw ngMinErr('cpi',
- "Can't copy! Source and destination are identical.");
- if (isArray(source)) {
- destination.length = 0;
- for ( var i = 0; i < source.length; i++) {
- destination.push(copy(source[i]));
- }
- } else {
- var h = destination.$$hashKey;
- forEach(destination, function(value, key){
- delete destination[key];
- });
- for ( var key in source) {
- destination[key] = copy(source[key]);
- }
- setHashKey(destination,h);
- }
- }
- return destination;
- }
- /**
- * Create a shallow copy of an object
- */
- function shallowCopy(src, dst) {
- dst = dst || {};
- for(var key in src) {
- // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
- // so we don't need to worry hasOwnProperty here
- if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
- dst[key] = src[key];
- }
- }
- return dst;
- }
- /**
- * @ngdoc function
- * @name angular.equals
- * @function
- *
- * @description
- * Determines if two objects or two values are equivalent. Supports value types, regular
- * expressions, arrays and objects.
- *
- * Two objects or values are considered equivalent if at least one of the following is true:
- *
- * * Both objects or values pass `===` comparison.
- * * Both objects or values are of the same type and all of their properties are equal by
- * comparing them with `angular.equals`.
- * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
- * * Both values represent the same regular expression (In JavasScript,
- * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
- * representation matches).
- *
- * During a property comparison, properties of `function` type and properties with names
- * that begin with `$` are ignored.
- *
- * Scope and DOMWindow objects are being compared only by identify (`===`).
- *
- * @param {*} o1 Object or value to compare.
- * @param {*} o2 Object or value to compare.
- * @returns {boolean} True if arguments are equal.
- */
- function equals(o1, o2) {
- if (o1 === o2) return true;
- 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)) {
- return isDate(o2) && o1.getTime() == o2.getTime();
- } else if (isRegExp(o1) && isRegExp(o2)) {
- return o1.toString() == o2.toString();
- } else {
- if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
- keySet = {};
- 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 (!keySet.hasOwnProperty(key) &&
- key.charAt(0) !== '$' &&
- o2[key] !== undefined &&
- !isFunction(o2[key])) return false;
- }
- return true;
- }
- }
- }
- return false;
- }
- function csp() {
- return (document.securityPolicy && document.securityPolicy.isActive) ||
- (document.querySelector &&
- !!(document.querySelector('[ng-csp]') || document.querySelector('[data-ng-csp]')));
- }
- function concat(array1, array2, index) {
- return array1.concat(slice.call(array2, index));
- }
- function sliceArgs(args, startIndex) {
- return slice.call(args, startIndex || 0);
- }
- /* jshint -W101 */
- /**
- * @ngdoc function
- * @name angular.bind
- * @function
- *
- * @description
- * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
- * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
- * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
- * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
- *
- * @param {Object} self Context which `fn` should be evaluated in.
- * @param {function()} fn Function to be bound.
- * @param {...*} args Optional arguments to be prebound to the `fn` function call.
- * @returns {function()} Function that wraps the `fn` with all the specified bindings.
- */
- /* jshint +W101 */
- function bind(self, fn) {
- var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
- if (isFunction(fn) && !(fn instanceof RegExp)) {
- return curryArgs.length
- ? function() {
- return arguments.length
- ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
- : fn.apply(self, curryArgs);
- }
- : function() {
- return arguments.length
- ? fn.apply(self, arguments)
- : fn.call(self);
- };
- } else {
- // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
- return fn;
- }
- }
- function toJsonReplacer(key, value) {
- var val = value;
- if (typeof key === 'string' && key.charAt(0) === '$') {
- val = undefined;
- } else if (isWindow(value)) {
- val = '$WINDOW';
- } else if (value && document === value) {
- val = '$DOCUMENT';
- } else if (isScope(value)) {
- val = '$SCOPE';
- }
- return val;
- }
- /**
- * @ngdoc function
- * @name angular.toJson
- * @function
- *
- * @description
- * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
- * stripped since angular uses this notation internally.
- *
- * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
- * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
- * @returns {string|undefined} JSON-ified string representing `obj`.
- */
- function toJson(obj, pretty) {
- if (typeof obj === 'undefined') return undefined;
- return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null);
- }
- /**
- * @ngdoc function
- * @name angular.fromJson
- * @function
- *
- * @description
- * Deserializes a JSON string.
- *
- * @param {string} json JSON string to deserialize.
- * @returns {Object|Array|Date|string|number} Deserialized thingy.
- */
- function fromJson(json) {
- return isString(json)
- ? JSON.parse(json)
- : json;
- }
- function toBoolean(value) {
- if (value && value.length !== 0) {
- var v = lowercase("" + value);
- value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
- } else {
- value = false;
- }
- return value;
- }
- /**
- * @returns {string} Returns the string representation of the element.
- */
- function startingTag(element) {
- element = jqLite(element).clone();
- try {
- // turns out IE does not let you set .html() on elements which
- // are not allowed to have children. So we just ignore it.
- element.html('');
- } catch(e) {}
- // As Per DOM Standards
- var TEXT_NODE = 3;
- var elemHtml = jqLite('<div>').append(element).html();
- try {
- return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
- elemHtml.
- match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
- } catch(e) {
- return lowercase(elemHtml);
- }
- }
- /////////////////////////////////////////////////
- /**
- * Tries to decode the URI component without throwing an exception.
- *
- * @private
- * @param str value potential URI component to check.
- * @returns {boolean} True if `value` can be decoded
- * with the decodeURIComponent function.
- */
- function tryDecodeURIComponent(value) {
- try {
- return decodeURIComponent(value);
- } catch(e) {
- // Ignore any invalid uri component
- }
- }
- /**
- * Parses an escaped url query string into key-value pairs.
- * @returns Object.<(string|boolean)>
- */
- function parseKeyValue(/**string*/keyValue) {
- var obj = {}, key_value, key;
- forEach((keyValue || "").split('&'), function(keyValue){
- if ( keyValue ) {
- key_value = keyValue.split('=');
- key = tryDecodeURIComponent(key_value[0]);
- if ( isDefined(key) ) {
- var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
- if (!obj[key]) {
- obj[key] = val;
- } else if(isArray(obj[key])) {
- obj[key].push(val);
- } else {
- obj[key] = [obj[key],val];
- }
- }
- }
- });
- return obj;
- }
- function toKeyValue(obj) {
- var parts = [];
- forEach(obj, function(value, key) {
- if (isArray(value)) {
- forEach(value, function(arrayValue) {
- parts.push(encodeUriQuery(key, true) +
- (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
- });
- } else {
- parts.push(encodeUriQuery(key, true) +
- (value === true ? '' : '=' + encodeUriQuery(value, true)));
- }
- });
- return parts.length ? parts.join('&') : '';
- }
- /**
- * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
- * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
- * segments:
- * segment = *pchar
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- * pct-encoded = "%" HEXDIG HEXDIG
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- * / "*" / "+" / "," / ";" / "="
- */
- function encodeUriSegment(val) {
- return encodeUriQuery(val, true).
- replace(/%26/gi, '&').
- replace(/%3D/gi, '=').
- replace(/%2B/gi, '+');
- }
- /**
- * This method is intended for encoding *key* or *value* parts of query component. We need a custom
- * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
- * encoded per http://tools.ietf.org/html/rfc3986:
- * query = *( pchar / "/" / "?" )
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- * pct-encoded = "%" HEXDIG HEXDIG
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- * / "*" / "+" / "," / ";" / "="
- */
- function encodeUriQuery(val, pctEncodeSpaces) {
- return encodeURIComponent(val).
- replace(/%40/gi, '@').
- replace(/%3A/gi, ':').
- replace(/%24/g, '$').
- replace(/%2C/gi, ',').
- replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
- }
- /**
- * @ngdoc directive
- * @name ng.directive:ngApp
- *
- * @element ANY
- * @param {angular.Module} ngApp an optional application
- * {@link angular.module module} name to load.
- *
- * @description
- *
- * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
- * designates the **root element** of the application and is typically placed near the root element
- * of the page - e.g. on the `<body>` or `<html>` tags.
- *
- * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
- * found in the document will be used to define the root element to auto-bootstrap as an
- * application. To run multiple applications in an HTML document you must manually bootstrap them using
- * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
- *
- * You can specify an **AngularJS module** to be used as the root module for the application. This
- * module will be loaded into the {@link AUTO.$injector} when the application is bootstrapped and
- * should contain the application code needed or have dependencies on other modules that will
- * contain the code. See {@link angular.module} for more information.
- *
- * In the example below if the `ngApp` directive were not placed on the `html` element then the
- * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
- * would not be resolved to `3`.
- *
- * `ngApp` is the easiest, and most common, way to bootstrap an application.
- *
- <example module="ngAppDemo">
- <file name="index.html">
- <div ng-controller="ngAppDemoController">
- I can add: {{a}} + {{b}} = {{ a+b }}
- </file>
- <file name="script.js">
- angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
- $scope.a = 1;
- $scope.b = 2;
- });
- </file>
- </example>
- *
- */
- function angularInit(element, bootstrap) {
- var elements = [element],
- appElement,
- module,
- names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
- NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
- function append(element) {
- element && elements.push(element);
- }
- forEach(names, function(name) {
- names[name] = true;
- append(document.getElementById(name));
- name = name.replace(':', '\\:');
- if (element.querySelectorAll) {
- forEach(element.querySelectorAll('.' + name), append);
- forEach(element.querySelectorAll('.' + name + '\\:'), append);
- forEach(element.querySelectorAll('[' + name + ']'), append);
- }
- });
- forEach(elements, function(element) {
- if (!appElement) {
- var className = ' ' + element.className + ' ';
- var match = NG_APP_CLASS_REGEXP.exec(className);
- if (match) {
- appElement = element;
- module = (match[2] || '').replace(/\s+/g, ',');
- } else {
- forEach(element.attributes, function(attr) {
- if (!appElement && names[attr.name]) {
- appElement = element;
- module = attr.value;
- }
- });
- }
- }
- });
- if (appElement) {
- bootstrap(appElement, module ? [module] : []);
- }
- }
- /**
- * @ngdoc function
- * @name angular.bootstrap
- * @description
- * Use this function to manually start up angular application.
- *
- * See: {@link guide/bootstrap Bootstrap}
- *
- * Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.
- * They must use {@link api/ng.directive:ngApp ngApp}.
- *
- * @param {Element} element DOM element which is the root of angular application.
- * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
- * Each item in the array should be the name of a predefined module or a (DI annotated)
- * function that will be invoked by the injector as a run block.
- * See: {@link angular.module modules}
- * @returns {AUTO.$injector} Returns the newly created injector for this app.
- */
- function bootstrap(element, modules) {
- var doBootstrap = function() {
- element = jqLite(element);
- if (element.injector()) {
- var tag = (element[0] === document) ? 'document' : startingTag(element);
- throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
- }
- modules = modules || [];
- modules.unshift(['$provide', function($provide) {
- $provide.value('$rootElement', element);
- }]);
- modules.unshift('ng');
- var injector = createInjector(modules);
- injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
- function(scope, element, compile, injector, animate) {
- scope.$apply(function() {
- element.data('$injector', injector);
- compile(element)(scope);
- });
- }]
- );
- return injector;
- };
- var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
- if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
- return doBootstrap();
- }
- window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
- angular.resumeBootstrap = function(extraModules) {
- forEach(extraModules, function(module) {
- modules.push(module);
- });
- doBootstrap();
- };
- }
- var SNAKE_CASE_REGEXP = /[A-Z]/g;
- function snake_case(name, separator){
- separator = separator || '_';
- return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
- return (pos ? separator : '') + letter.toLowerCase();
- });
- }
- function bindJQuery() {
- // bind to jQuery if present;
- jQuery = window.jQuery;
- // reset to jQuery or default to us.
- if (jQuery) {
- jqLite = jQuery;
- extend(jQuery.fn, {
- scope: JQLitePrototype.scope,
- isolateScope: JQLitePrototype.isolateScope,
- controller: JQLitePrototype.controller,
- injector: JQLitePrototype.injector,
- inheritedData: JQLitePrototype.inheritedData
- });
- // Method signature:
- // jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
- jqLitePatchJQueryRemove('remove', true, true, false);
- jqLitePatchJQueryRemove('empty', false, false, false);
- jqLitePatchJQueryRemove('html', false, false, true);
- } else {
- jqLite = JQLite;
- }
- angular.element = jqLite;
- }
- /**
- * throw error if the argument is falsy.
- */
- function assertArg(arg, name, reason) {
- if (!arg) {
- throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
- }
- return arg;
- }
- function assertArgFn(arg, name, acceptArrayAnnotation) {
- if (acceptArrayAnnotation && isArray(arg)) {
- arg = arg[arg.length - 1];
- }
- assertArg(isFunction(arg), name, 'not a function, got ' +
- (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
- return arg;
- }
- /**
- * throw error if the name given is hasOwnProperty
- * @param {String} name the name to test
- * @param {String} context the context in which the name is used, such as module or directive
- */
- function assertNotHasOwnProperty(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
- }
- }
- /**
- * Return the value accessible from the object by path. Any undefined traversals are ignored
- * @param {Object} obj starting object
- * @param {string} path path to traverse
- * @param {boolean=true} bindFnToScope
- * @returns value as accessible by path
- */
- //TODO(misko): this function needs to be removed
- function getter(obj, path, bindFnToScope) {
- if (!path) return obj;
- var keys = path.split('.');
- var key;
- var lastInstance = obj;
- var len = keys.length;
- for (var i = 0; i < len; i++) {
- key = keys[i];
- if (obj) {
- obj = (lastInstance = obj)[key];
- }
- }
- if (!bindFnToScope && isFunction(obj)) {
- return bind(lastInstance, obj);
- }
- return obj;
- }
- /**
- * Return the siblings between `startNode` and `endNode`, inclusive
- * @param {Object} object with `startNode` and `endNode` properties
- * @returns jQlite object containing the elements
- */
- function getBlockElements(block) {
- if (block.startNode === block.endNode) {
- return jqLite(block.startNode);
- }
- var element = block.startNode;
- var elements = [element];
- do {
- element = element.nextSibling;
- if (!element) break;
- elements.push(element);
- } while (element !== block.endNode);
- return jqLite(elements);
- }
- /**
- * @ngdoc interface
- * @name angular.Module
- * @description
- *
- * Interface for configuring angular {@link angular.module modules}.
- */
- function setupModuleLoader(window) {
- var $injectorMinErr = minErr('$injector');
- var ngMinErr = minErr('ng');
- function ensure(obj, name, factory) {
- return obj[name] || (obj[name] = factory());
- }
- var angular = ensure(window, 'angular', Object);
- // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
- angular.$$minErr = angular.$$minErr || minErr;
- return ensure(angular, 'module', function() {
- /** @type {Object.<string, angular.Module>} */
- var modules = {};
- /**
- * @ngdoc function
- * @name angular.module
- * @description
- *
- * The `angular.module` is a global place for creating, registering and retrieving Angular
- * modules.
- * 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.
- *
- *
- * # Module
- *
- * A module is a collection of services, directives, filters, and configuration information.
- * `angular.module` is used to configure the {@link AUTO.$injector $injector}.
- *
- * <pre>
- * // Create a new module
- * var myModule = angular.module('myModule', []);
- *
- * // register a new service
- * myModule.value('appName', 'MyCoolApp');
- *
- * // configure existing services inside initialization blocks.
- * myModule.config(function($locationProvider) {
- * // Configure existing providers
- * $locationProvider.hashPrefix('!');
- * });
- * </pre>
- *
- * Then you can create an injector and load your modules like this:
- *
- * <pre>
- * var injector = angular.injector(['ng', 'MyModule'])
- * </pre>
- *
- * 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.<string>=} requires If specified then new module is being created. If
- * unspecified then the the module is being retrieved for further configuration.
- * @param {Function} configFn Optional configuration function for the module. Same as
- * {@link angular.Module#methods_config Module#config()}.
- * @returns {module} new module with the {@link angular.Module} api.
- */
- return function module(name, requires, configFn) {
- var assertNotHasOwnProperty = function(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
- }
- };
- assertNotHasOwnProperty(name, 'module');
- if (requires && modules.hasOwnProperty(name)) {
- modules[name] = null;
- }
- return ensure(modules, name, function() {
- if (!requires) {
- throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
- "the module name or forgot to load it. If registering a module ensure that you " +
- "specify the dependencies as the second argument.", name);
- }
- /** @type {!Array.<Array.<*>>} */
- var invokeQueue = [];
- /** @type {!Array.<Function>} */
- var runBlocks = [];
- var config = invokeLater('$injector', 'invoke');
- /** @type {angular.Module} */
- var moduleInstance = {
- // Private state
- _invokeQueue: invokeQueue,
- _runBlocks: runBlocks,
- /**
- * @ngdoc property
- * @name angular.Module#requires
- * @propertyOf angular.Module
- * @returns {Array.<string>} List of module names which must be loaded before this module.
- * @description
- * Holds the list of modules which the injector will load before the current module is
- * loaded.
- */
- requires: requires,
- /**
- * @ngdoc property
- * @name angular.Module#name
- * @propertyOf angular.Module
- * @returns {string} Name of the module.
- * @description
- */
- name: name,
- /**
- * @ngdoc method
- * @name angular.Module#provider
- * @methodOf angular.Module
- * @param {string} name service name
- * @param {Function} providerType Construction function for creating new instance of the
- * service.
- * @description
- * See {@link AUTO.$provide#provider $provide.provider()}.
- */
- provider: invokeLater('$provide', 'provider'),
- /**
- * @ngdoc method
- * @name angular.Module#factory
- * @methodOf angular.Module
- * @param {string} name service name
- * @param {Function} providerFunction Function for creating new instance of the service.
- * @description
- * See {@link AUTO.$provide#factory $provide.factory()}.
- */
- factory: invokeLater('$provide', 'factory'),
- /**
- * @ngdoc method
- * @name angular.Module#service
- * @methodOf angular.Module
- * @param {string} name service name
- * @param {Function} constructor A constructor function that will be instantiated.
- * @description
- * See {@link AUTO.$provide#service $provide.service()}.
- */
- service: invokeLater('$provide', 'service'),
- /**
- * @ngdoc method
- * @name angular.Module#value
- * @methodOf angular.Module
- * @param {string} name service name
- * @param {*} object Service instance object.
- * @description
- * See {@link AUTO.$provide#value $provide.value()}.
- */
- value: invokeLater('$provide', 'value'),
- /**
- * @ngdoc method
- * @name angular.Module#constant
- * @methodOf angular.Module
- * @param {string} name constant name
- * @param {*} object Constant value.
- * @description
- * Because the constant 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#animation
- * @methodOf angular.Module
- * @param {string} name animation name
- * @param {Function} animationFactory Factory function for creating new instance of an
- * animation.
- * @description
- *
- * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
- *
- *
- * Defines an animation hook that can be later used with
- * {@link ngAnimate.$animate $animate} service and directives that use this service.
- *
- * <pre>
- * module.animation('.animation-name', function($inject1, $inject2) {
- * return {
- * eventName : function(element, done) {
- * //code to run the animation
- * //once complete, then run done()
- * return function cancellationFunction(element) {
- * //code to cancel the animation
- * }
- * }
- * }
- * })
- * </pre>
- *
- * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
- * {@link ngAnimate ngAnimate module} for more information.
- */
- animation: invokeLater('$animateProvider', 'register'),
- /**
- * @ngdoc method
- * @name angular.Module#filter
- * @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()}.
- */
- filter: invokeLater('$filterProvider', 'register'),
- /**
- * @ngdoc method
- * @name angular.Module#controller
- * @methodOf angular.Module
- * @param {string|Object} name Controller name, or an object map of controllers where the
- * keys are the names and the values are the constructors.
- * @param {Function} constructor Controller constructor function.
- * @description
- * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
- */
- controller: invokeLater('$controllerProvider', 'register'),
- /**
- * @ngdoc method
- * @name angular.Module#directive
- * @methodOf angular.Module
- * @param {string|Object} name Directive name, or an object map of directives where the
- * keys are the names and the values are the factories.
- * @param {Function} directiveFactory Factory function for creating new instance of
- * directives.
- * @description
- * See {@link ng.$compileProvider#methods_directive $compileProvider.directive()}.
- */
- directive: invokeLater('$compileProvider', 'directive'),
- /**
- * @ngdoc method
- * @name angular.Module#config
- * @methodOf angular.Module
- * @param {Function} configFn Execute this function on module load. Useful for service
- * configuration.
- * @description
- * Use this method to register work which needs to be performed on module loading.
- */
- config: config,
- /**
- * @ngdoc method
- * @name angular.Module#run
- * @methodOf angular.Module
- * @param {Function} initializationFn Execute this function after injector creation.
- * Useful for application init