diff --git a/config/karma.js b/config/karma.js index e90add650..44a0c6a81 100644 --- a/config/karma.js +++ b/config/karma.js @@ -7,9 +7,8 @@ basePath = '..'; files = [ JASMINE, JASMINE_ADAPTER, - 'lib/angular-1.2.0-rc.2/angular.js', - 'lib/angular-1.2.0-rc.2/angular-animate.js', - 'lib/angular-1.2.0-rc.2/angular-mocks.js', + 'lib/angular-1.2.0.js', + 'test/lib/angular-mocks-1.2.0.js', 'test/testUtils.js', 'src/common.js', diff --git a/lib/angular-1.2.0.js b/lib/angular-1.2.0.js new file mode 100644 index 000000000..fc5ab04f4 --- /dev/null +++ b/lib/angular-1.2.0.js @@ -0,0 +1,20031 @@ +/** + * @license AngularJS v1.2.0 + * (c) 2010-2012 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 (isFunction(obj)) { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (isUndefined(obj)) { + return 'undefined'; + } else if (!isString(obj)) { + 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 (isFunction(arg)) { + return arg.toString().replace(/ ?\{[\s\S]*$/, ''); + } else if (isUndefined(arg)) { + return 'undefined'; + } else if (!isString(arg)) { + return toJson(arg); + } + return arg; + } + return match; + }); + + message = message + '\nhttp://errors.angularjs.org/' + version.full + '/' + + (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`. + * +
+ 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']);
+
+ *
+ * @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.
+
+ function foo(callback) {
+ var result = calculateResult();
+ (callback || angular.noop)(result);
+ }
+
+ */
+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.
+ *
+
+ function transformer(transformationFn, value) {
+ return (transformationFn || angular.identity)(value);
+ };
+
+ */
+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*/, '').replace(/\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
+ form = {{user | json}}
+ master = {{master | json}}
+
+ * // 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('!');
+ * });
+ *
+ *
+ * Then you can create an injector and load your modules like this:
+ *
+ * + * 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) {
+ * //code to run the animation
+ * //once complete, then run done()
+ * return function cancellationFunction(element) {
+ * //code to cancel the animation
+ * }
+ * }
+ * }
+ * })
+ *
+ *
+ * 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 initialization.
+ * @description
+ * Use this method to register work which should be performed when the injector is done
+ * loading all modules.
+ */
+ run: function(block) {
+ runBlocks.push(block);
+ return this;
+ }
+ };
+
+ if (configFn) {
+ config(configFn);
+ }
+
+ return moduleInstance;
+
+ /**
+ * @param {string} provider
+ * @param {string} method
+ * @param {String=} insertMethod
+ * @returns {angular.Module}
+ */
+ function invokeLater(provider, method, insertMethod) {
+ return function() {
+ invokeQueue[insertMethod || 'push']([provider, method, arguments]);
+ return moduleInstance;
+ };
+ }
+ });
+ };
+ });
+
+}
+
+/* global
+ angularModule: true,
+ version: true,
+
+ $LocaleProvider,
+ $CompileProvider,
+
+ htmlAnchorDirective,
+ inputDirective,
+ inputDirective,
+ formDirective,
+ scriptDirective,
+ selectDirective,
+ styleDirective,
+ optionDirective,
+ ngBindDirective,
+ ngBindHtmlDirective,
+ ngBindTemplateDirective,
+ ngClassDirective,
+ ngClassEvenDirective,
+ ngClassOddDirective,
+ ngCspDirective,
+ ngCloakDirective,
+ ngControllerDirective,
+ ngFormDirective,
+ ngHideDirective,
+ ngIfDirective,
+ ngIncludeDirective,
+ ngInitDirective,
+ ngNonBindableDirective,
+ ngPluralizeDirective,
+ ngRepeatDirective,
+ ngShowDirective,
+ ngStyleDirective,
+ ngSwitchDirective,
+ ngSwitchWhenDirective,
+ ngSwitchDefaultDirective,
+ ngOptionsDirective,
+ ngTranscludeDirective,
+ ngModelDirective,
+ ngListDirective,
+ ngChangeDirective,
+ requiredDirective,
+ requiredDirective,
+ ngValueDirective,
+ ngAttributeAliasDirectives,
+ ngEventDirectives,
+
+ $AnchorScrollProvider,
+ $AnimateProvider,
+ $BrowserProvider,
+ $CacheFactoryProvider,
+ $ControllerProvider,
+ $DocumentProvider,
+ $ExceptionHandlerProvider,
+ $FilterProvider,
+ $InterpolateProvider,
+ $IntervalProvider,
+ $HttpProvider,
+ $HttpBackendProvider,
+ $LocationProvider,
+ $LogProvider,
+ $ParseProvider,
+ $RootScopeProvider,
+ $QProvider,
+ $SceProvider,
+ $SceDelegateProvider,
+ $SnifferProvider,
+ $TemplateCacheProvider,
+ $TimeoutProvider,
+ $WindowProvider
+*/
+
+
+/**
+ * @ngdoc property
+ * @name angular.version
+ * @description
+ * An object that contains information about the current AngularJS version. This object has the
+ * following properties:
+ *
+ * - `full` – `{string}` – Full version string, such as "0.9.18".
+ * - `major` – `{number}` – Major version number, such as "0".
+ * - `minor` – `{number}` – Minor version number, such as "9".
+ * - `dot` – `{number}` – Dot version number, such as "18".
+ * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
+ */
+var version = {
+ full: '1.2.0', // all of these placeholder strings will be replaced by grunt's
+ major: 1, // package task
+ minor: "NG_VERSION_MINOR",
+ dot: 0,
+ codeName: 'timely-delivery'
+};
+
+
+function publishExternalAPI(angular){
+ extend(angular, {
+ 'bootstrap': bootstrap,
+ 'copy': copy,
+ 'extend': extend,
+ 'equals': equals,
+ 'element': jqLite,
+ 'forEach': forEach,
+ 'injector': createInjector,
+ 'noop':noop,
+ 'bind':bind,
+ 'toJson': toJson,
+ 'fromJson': fromJson,
+ 'identity':identity,
+ 'isUndefined': isUndefined,
+ 'isDefined': isDefined,
+ 'isString': isString,
+ 'isFunction': isFunction,
+ 'isObject': isObject,
+ 'isNumber': isNumber,
+ 'isElement': isElement,
+ 'isArray': isArray,
+ 'version': version,
+ 'isDate': isDate,
+ 'lowercase': lowercase,
+ 'uppercase': uppercase,
+ 'callbacks': {counter: 0},
+ '$$minErr': minErr,
+ '$$csp': csp
+ });
+
+ angularModule = setupModuleLoader(window);
+ try {
+ angularModule('ngLocale');
+ } catch (e) {
+ angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
+ }
+
+ angularModule('ng', ['ngLocale'], ['$provide',
+ function ngModule($provide) {
+ $provide.provider('$compile', $CompileProvider).
+ directive({
+ a: htmlAnchorDirective,
+ input: inputDirective,
+ textarea: inputDirective,
+ form: formDirective,
+ script: scriptDirective,
+ select: selectDirective,
+ style: styleDirective,
+ option: optionDirective,
+ ngBind: ngBindDirective,
+ ngBindHtml: ngBindHtmlDirective,
+ ngBindTemplate: ngBindTemplateDirective,
+ ngClass: ngClassDirective,
+ ngClassEven: ngClassEvenDirective,
+ ngClassOdd: ngClassOddDirective,
+ ngCloak: ngCloakDirective,
+ ngController: ngControllerDirective,
+ ngForm: ngFormDirective,
+ ngHide: ngHideDirective,
+ ngIf: ngIfDirective,
+ ngInclude: ngIncludeDirective,
+ ngInit: ngInitDirective,
+ ngNonBindable: ngNonBindableDirective,
+ ngPluralize: ngPluralizeDirective,
+ ngRepeat: ngRepeatDirective,
+ ngShow: ngShowDirective,
+ ngStyle: ngStyleDirective,
+ ngSwitch: ngSwitchDirective,
+ ngSwitchWhen: ngSwitchWhenDirective,
+ ngSwitchDefault: ngSwitchDefaultDirective,
+ ngOptions: ngOptionsDirective,
+ ngTransclude: ngTranscludeDirective,
+ ngModel: ngModelDirective,
+ ngList: ngListDirective,
+ ngChange: ngChangeDirective,
+ required: requiredDirective,
+ ngRequired: requiredDirective,
+ ngValue: ngValueDirective
+ }).
+ directive(ngAttributeAliasDirectives).
+ directive(ngEventDirectives);
+ $provide.provider({
+ $anchorScroll: $AnchorScrollProvider,
+ $animate: $AnimateProvider,
+ $browser: $BrowserProvider,
+ $cacheFactory: $CacheFactoryProvider,
+ $controller: $ControllerProvider,
+ $document: $DocumentProvider,
+ $exceptionHandler: $ExceptionHandlerProvider,
+ $filter: $FilterProvider,
+ $interpolate: $InterpolateProvider,
+ $interval: $IntervalProvider,
+ $http: $HttpProvider,
+ $httpBackend: $HttpBackendProvider,
+ $location: $LocationProvider,
+ $log: $LogProvider,
+ $parse: $ParseProvider,
+ $rootScope: $RootScopeProvider,
+ $q: $QProvider,
+ $sce: $SceProvider,
+ $sceDelegate: $SceDelegateProvider,
+ $sniffer: $SnifferProvider,
+ $templateCache: $TemplateCacheProvider,
+ $timeout: $TimeoutProvider,
+ $window: $WindowProvider
+ });
+ }
+ ]);
+}
+
+/* global
+
+ -JQLitePrototype,
+ -addEventListenerFn,
+ -removeEventListenerFn,
+ -BOOLEAN_ATTR
+*/
+
+//////////////////////////////////
+//JQLite
+//////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.element
+ * @function
+ *
+ * @description
+ * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
+ *
+ * If jQuery is available, `angular.element` is an alias for the
+ * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
+ * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
+ *
+ *
+ * // 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){
+ * $compile($document)($rootScope);
+ * $rootScope.$digest();
+ * });
+ *
+ */
+
+
+/**
+ * @ngdoc overview
+ * @name AUTO
+ * @description
+ *
+ * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
+ */
+
+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 annotate(fn) {
+ var $inject,
+ fnText,
+ argDecl,
+ last;
+
+ if (typeof fn == 'function') {
+ if (!($inject = fn.$inject)) {
+ $inject = [];
+ if (fn.length) {
+ 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);
+ });
+ });
+ }
+ fn.$inject = $inject;
+ }
+ } else if (isArray(fn)) {
+ last = fn.length - 1;
+ assertArgFn(fn[last], 'fn');
+ $inject = fn.slice(0, last);
+ } else {
+ assertArgFn(fn, 'fn', true);
+ }
+ return $inject;
+}
+
+///////////////////////////////////////
+
+/**
+ * @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,
+ * and load modules.
+ *
+ * The following always holds true:
+ *
+ *
+ * var $injector = angular.injector();
+ * expect($injector.get('$injector')).toBe($injector);
+ * expect($injector.invoke(function($injector){
+ * return $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.
+ *
+ *
+ * // inferred (only works if code not minified/obfuscated)
+ * $injector.invoke(function(serviceA){});
+ *
+ * // annotated
+ * function explicit(serviceA) {};
+ * explicit.$inject = ['serviceA'];
+ * $injector.invoke(explicit);
+ *
+ * // 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. *NOTE:* This does not work with
+ * minification, and obfuscation tools since these tools change the argument names.
+ *
+ * ## `$inject` Annotation
+ * 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.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#get
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Return an instance of the service.
+ *
+ * @param {string} name The name of the instance to retrieve.
+ * @return {*} The instance.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#invoke
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Invoke the method and supply the method arguments from the `$injector`.
+ *
+ * @param {!function} fn The function to invoke. Function parameters are injected according to the
+ * {@link guide/di $inject Annotation} rules.
+ * @param {Object=} self The `this` for the invoked method.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
+ * object first, before the `$injector` is consulted.
+ * @returns {*} the value returned by the invoked `fn` function.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#has
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Allows the user to query if the particular service exist.
+ *
+ * @param {string} Name of the service to query.
+ * @returns {boolean} returns true if injector has given service.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#instantiate
+ * @methodOf AUTO.$injector
+ * @description
+ * Create a new instance of JS type. The method takes a constructor function invokes the new
+ * operator and supplies all of the arguments to the constructor function as specified by the
+ * constructor annotation.
+ *
+ * @param {function} Type Annotated constructor function.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
+ * object first, before the `$injector` is consulted.
+ * @returns {Object} new instance of `Type`.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#annotate
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Returns an array of service names which the function is requesting for injection. This API is
+ * used by the injector to determine which services need to be injected into the function when the
+ * function is invoked. There are three ways in which the function can be annotated with the needed
+ * dependencies.
+ *
+ * # Argument names
+ *
+ * The simplest form is to extract the dependencies from the arguments of the function. This is done
+ * by converting the function into a string using `toString()` method and extracting the argument
+ * names.
+ *
+ * // Given
+ * function MyController($scope, $route) {
+ * // ...
+ * }
+ *
+ * // Then
+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ *
+ *
+ * This method does not work with code minification / obfuscation. For this reason the following
+ * annotation strategies are supported.
+ *
+ * # The `$inject` property
+ *
+ * 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.
+ *
+ * // Given
+ * var MyController = function(obfuscatedScope, obfuscatedRoute) {
+ * // ...
+ * }
+ * // Define function dependencies
+ * MyController.$inject = ['$scope', '$route'];
+ *
+ * // Then
+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ *
+ *
+ * # The array notation
+ *
+ * It is often desirable to inline Injected functions and that's when setting the `$inject` property
+ * is very inconvenient. In these situations using the array notation to specify the dependencies in
+ * a way that survives minification is a better choice:
+ *
+ *
+ * // We wish to write this (not minification / obfuscation safe)
+ * injector.invoke(function($compile, $rootScope) {
+ * // ...
+ * });
+ *
+ * // We are forced to write break inlining
+ * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
+ * // ...
+ * };
+ * tmpFn.$inject = ['$compile', '$rootScope'];
+ * injector.invoke(tmpFn);
+ *
+ * // To better support inline function the inline annotation is supported
+ * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
+ * // ...
+ * }]);
+ *
+ * // Therefore
+ * 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';
+ *
+ * // A provider method for configuring where the tracked events should been saved
+ * this.setTrackingUrl = function(url) {
+ * trackingUrl = url;
+ * };
+ *
+ * // The service factory function
+ * this.$get = ['$http', function($http) {
+ * var trackedEvents = {};
+ * return {
+ * // Call this to track an event
+ * event: function(event) {
+ * var count = trackedEvents[event] || 0;
+ * count += 1;
+ * trackedEvents[event] = count;
+ * return count;
+ * },
+ * // Call this to save the tracked events to the trackingUrl
+ * save: function() {
+ * $http.post(trackingUrl, trackedEvents);
+ * }
+ * };
+ * }];
+ * }
+ *
+ * describe('eventTracker', function() {
+ * var postSpy;
+ *
+ * beforeEach(module(function($provide) {
+ * // Register the eventTracker provider
+ * $provide.provider('eventTracker', EventTrackerProvider);
+ * }));
+ *
+ * beforeEach(module(function(eventTrackerProvider) {
+ * // Configure eventTracker provider
+ * eventTrackerProvider.setTrackingUrl('/custom-track');
+ * }));
+ *
+ * it('tracks events', inject(function(eventTracker) {
+ * expect(eventTracker.event('login')).toEqual(1);
+ * expect(eventTracker.event('login')).toEqual(2);
+ * }));
+ *
+ * it('saves to the tracking url', inject(function(eventTracker, $http) {
+ * postSpy = spyOn($http, 'post');
+ * eventTracker.event('login');
+ * eventTracker.save();
+ * expect(postSpy).toHaveBeenCalled();
+ * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
+ * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
+ * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
+ * }));
+ * });
+ *
+ */
+
+/**
+ * @ngdoc method
+ * @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
+ * configure your service in a provider.
+ *
+ * @param {string} name The name of the instance.
+ * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
+ * for `$provide.provider(name, {$get: $getFn})`.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here is an example of registering a service
+ *
+ * $provide.factory('ping', ['$http', function($http) {
+ * return function ping() {
+ * return $http.send('/ping');
+ * };
+ * }]);
+ *
+ * You would then inject and use this service like this:
+ *
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping();
+ * }]);
+ *
+ */
+
+
+/**
+ * @ngdoc method
+ * @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 the service
+ * constructor function that will be used to instantiate the service instance.
+ *
+ * You should use {@link AUTO.$provide#methods_service $provide.service(class)} if you define your service
+ * as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function} constructor A class (constructor function) that will be instantiated.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here is an example of registering a service using
+ * {@link AUTO.$provide#methods_service $provide.service(class)} that is defined as a CoffeeScript class.
+ *
+ * class Ping
+ * constructor: (@$http)->
+ * send: ()=>
+ * @$http.get('/ping')
+ *
+ * $provide.service('ping', ['$http', Ping])
+ *
+ * You would then inject and use this service like this:
+ * + * someModule.controller 'Ctrl', ['ping', (ping)-> + * ping.send() + * ] + *+ */ + + +/** + * @ngdoc method + * @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 + * provider's `$get` property is a factory function that takes no arguments and returns the **value + * 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}. + * + * @param {string} name The name of the instance. + * @param {*} value The value. + * @returns {Object} registered provider instance + * + * @example + * Here are some examples of creating value services. + *
+ * $provide.constant('ADMIN_USER', 'admin');
+ *
+ * $provide.constant('RoleLookup', { admin: 0, writer: 1, reader: 2 });
+ *
+ * $provide.constant('halfOf', function(value) {
+ * return value / 2;
+ * });
+ *
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#constant
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * 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}.
+ *
+ * @param {string} name The name of the constant.
+ * @param {*} value The constant value.
+ * @returns {Object} registered instance
+ *
+ * @example
+ * Here a some examples of creating constants:
+ *
+ * $provide.constant('SHARD_HEIGHT', 306);
+ *
+ * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
+ *
+ * $provide.constant('double', function(value) {
+ * return value * 2;
+ * });
+ *
+ */
+
+
+/**
+ * @ngdoc method
+ * @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 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()} decorator This function will be invoked when the service needs to be
+ * instantiated and should return the decorated service instance. The function is called using
+ * the {@link AUTO.$injector#invoke injector.invoke} method and is therefore fully injectable.
+ * Local injection arguments:
+ *
+ * * `$delegate` - The original service instance, which can be monkey patched, configured,
+ * decorated or delegated to.
+ *
+ * @example
+ * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
+ * calls to {@link ng.$log#error $log.warn()}.
+ *
+ * $provider.decorator('$log', ['$delegate', function($delegate) {
+ * $delegate.warn = $delegate.error;
+ * return $delegate;
+ * }]);
+ *
+ */
+
+
+function createInjector(modulesToLoad) {
+ var INSTANTIATING = {},
+ providerSuffix = 'Provider',
+ path = [],
+ loadedModules = new HashMap(),
+ providerCache = {
+ $provide: {
+ provider: supportObject(provider),
+ factory: supportObject(factory),
+ service: supportObject(service),
+ value: supportObject(value),
+ constant: supportObject(constant),
+ decorator: decorator
+ }
+ },
+ providerInjector = (providerCache.$injector =
+ createInternalInjector(providerCache, function() {
+ throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
+ })),
+ instanceCache = {},
+ instanceInjector = (instanceCache.$injector =
+ createInternalInjector(instanceCache, function(servicename) {
+ var provider = providerInjector.get(servicename + providerSuffix);
+ return instanceInjector.invoke(provider.$get, provider);
+ }));
+
+
+ forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
+
+ return instanceInjector;
+
+ ////////////////////////////////////
+ // $provider
+ ////////////////////////////////////
+
+ function supportObject(delegate) {
+ return function(key, value) {
+ if (isObject(key)) {
+ forEach(key, reverseParams(delegate));
+ } else {
+ return delegate(key, value);
+ }
+ };
+ }
+
+ function provider(name, provider_) {
+ assertNotHasOwnProperty(name, 'service');
+ if (isFunction(provider_) || isArray(provider_)) {
+ provider_ = providerInjector.instantiate(provider_);
+ }
+ if (!provider_.$get) {
+ throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
+ }
+ return providerCache[name + providerSuffix] = provider_;
+ }
+
+ function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
+
+ function service(name, constructor) {
+ return factory(name, ['$injector', function($injector) {
+ return $injector.instantiate(constructor);
+ }]);
+ }
+
+ function value(name, val) { return factory(name, valueFn(val)); }
+
+ function constant(name, value) {
+ assertNotHasOwnProperty(name, 'constant');
+ providerCache[name] = value;
+ instanceCache[name] = value;
+ }
+
+ function decorator(serviceName, decorFn) {
+ var origProvider = providerInjector.get(serviceName + providerSuffix),
+ orig$get = origProvider.$get;
+
+ origProvider.$get = function() {
+ var origInstance = instanceInjector.invoke(orig$get, origProvider);
+ return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
+ };
+ }
+
+ ////////////////////////////////////
+ // Module Loading
+ ////////////////////////////////////
+ function loadModules(modulesToLoad){
+ var runBlocks = [], moduleFn, invokeQueue, i, ii;
+ forEach(modulesToLoad, function(module) {
+ if (loadedModules.get(module)) return;
+ loadedModules.put(module, true);
+
+ try {
+ if (isString(module)) {
+ moduleFn = angularModule(module);
+ runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
+
+ 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)) {
+ runBlocks.push(providerInjector.invoke(module));
+ } else {
+ assertArgFn(module, 'module');
+ }
+ } catch (e) {
+ if (isArray(module)) {
+ module = module[module.length - 1];
+ }
+ if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
+ // Safari & FF's stack traces don't contain error.message content
+ // unlike those of Chrome and IE
+ // So if stack doesn't contain message, we create a new string that contains both.
+ // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
+ /* jshint -W022 */
+ e = e.message + '\n' + e.stack;
+ }
+ throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
+ module, e.stack || e.message || e);
+ }
+ });
+ return runBlocks;
+ }
+
+ ////////////////////////////////////
+ // internal Injector
+ ////////////////////////////////////
+
+ function createInternalInjector(cache, factory) {
+
+ function getService(serviceName) {
+ if (cache.hasOwnProperty(serviceName)) {
+ if (cache[serviceName] === INSTANTIATING) {
+ 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);
+ } finally {
+ path.shift();
+ }
+ }
+ }
+
+ function invoke(fn, self, locals){
+ var args = [],
+ $inject = annotate(fn),
+ length, i,
+ key;
+
+ 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)
+ );
+ }
+ if (!fn.$inject) {
+ // this means that we must be an array.
+ fn = fn[length];
+ }
+
+
+ // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
+ switch (self ? -1 : args.length) {
+ case 0: return fn();
+ case 1: return fn(args[0]);
+ case 2: return fn(args[0], args[1]);
+ case 3: return fn(args[0], args[1], args[2]);
+ case 4: return fn(args[0], args[1], args[2], args[3]);
+ case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
+ case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
+ args[8]);
+ case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
+ args[8], args[9]);
+ default: return fn.apply(self, args);
+ }
+ }
+
+ function instantiate(Type, locals) {
+ var Constructor = function() {},
+ instance, returnedValue;
+
+ // 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) {}]);
+ 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: annotate,
+ has: function(name) {
+ return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
+ }
+ };
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name ng.$anchorScroll
+ * @requires $window
+ * @requires $location
+ * @requires $rootScope
+ *
+ * @description
+ * 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 {
+ * 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.
+ * @param {function} factory The factory function that will be executed to return the animation
+ * object.
+ */
+ this.register = function(name, factory) {
+ var key = name + '-animation';
+ 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);
+ };
+
+ this.$get = ['$timeout', function($timeout) {
+
+ /**
+ *
+ * @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.
+ *
+ * $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} as well as the {@link ngAnimate.$animate ngAnimate $animate service
+ * page}.
+ */
+ return {
+
+ /**
+ *
+ * @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
+ */
+ enter : function(element, parent, after, done) {
+ var afterNode = after && after[after.length - 1];
+ var parentNode = parent && parent[0] || afterNode && afterNode.parentNode;
+ // IE does not like undefined so we have to pass null.
+ var afterNextSibling = (afterNode && afterNode.nextSibling) || null;
+ forEach(element, function(node) {
+ parentNode.insertBefore(node, afterNextSibling);
+ });
+ done && $timeout(done, 0, false);
+ },
+
+ /**
+ *
+ * @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
+ */
+ leave : function(element, done) {
+ element.remove();
+ done && $timeout(done, 0, false);
+ },
+
+ /**
+ *
+ * @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, 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 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
+ */
+ 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 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
+ */
+ 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);
+ },
+
+ enabled : noop
+ };
+ }];
+}];
+
+/**
+ * ! This is a private undocumented service !
+ *
+ * @name ng.$browser
+ * @requires $log
+ * @description
+ * This object has two goals:
+ *
+ * - hide all the global state in the browser caused by the window object
+ * - abstract away all the browser specific features and inconsistencies
+ *
+ * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
+ * service, which can be used for convenient testing of the application without the interaction with
+ * the real browser apis.
+ */
+/**
+ * @param {object} window The global window object.
+ * @param {object} document jQuery wrapped document.
+ * @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,
+ clearTimeout = window.clearTimeout,
+ pendingDeferIds = {};
+
+ self.isMock = false;
+
+ var outstandingRequestCount = 0;
+ var outstandingRequestCallbacks = [];
+
+ // TODO(vojta): remove this temporary api
+ self.$$completeOutstandingRequest = completeOutstandingRequest;
+ self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
+
+ /**
+ * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
+ * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
+ */
+ function completeOutstandingRequest(fn) {
+ try {
+ fn.apply(null, sliceArgs(arguments, 1));
+ } finally {
+ outstandingRequestCount--;
+ if (outstandingRequestCount === 0) {
+ while(outstandingRequestCallbacks.length) {
+ try {
+ outstandingRequestCallbacks.pop()();
+ } catch (e) {
+ $log.error(e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @private
+ * Note: this method is used only by scenario runner
+ * TODO(vojta): prefix this method with $$ ?
+ * @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 {
+ outstandingRequestCallbacks.push(callback);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////
+ // 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 lastBrowserUrl = location.href,
+ baseElement = document.find('base'),
+ newLocation = null;
+
+ /**
+ * @name ng.$browser#url
+ * @methodOf ng.$browser
+ *
+ * @description
+ * GETTER:
+ * Without any argument, this method just returns current value of location.href.
+ *
+ * SETTER:
+ * With at least one argument, this method sets url to new value.
+ * If html5 history api supported, pushState/replaceState is used, otherwise
+ * location.href/location.replace is used.
+ * Returns its own instance to allow chaining
+ *
+ * NOTE: this api is intended for use only by the $location service. Please use the
+ * {@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 ?
+ */
+ self.url = function(url, replace) {
+ // Android Browser BFCache causes location reference to become stale.
+ if (location !== window.location) location = window.location;
+
+ // setter
+ if (url) {
+ if (lastBrowserUrl == url) return;
+ lastBrowserUrl = 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 {
+ location.href = url;
+ }
+ }
+ return self;
+ // getter
+ } else {
+ // - 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 newLocation || location.href.replace(/%27/g,"'");
+ }
+ };
+
+ var urlChangeListeners = [],
+ urlChangeInit = false;
+
+ function fireUrlChange() {
+ newLocation = null;
+ if (lastBrowserUrl == self.url()) return;
+
+ lastBrowserUrl = self.url();
+ forEach(urlChangeListeners, function(listener) {
+ listener(self.url());
+ });
+ }
+
+ /**
+ * @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.
+ *
+ * It's only called when the url is changed by outside of angular:
+ * - user types different url into address bar
+ * - user clicks on history (forward/back) button
+ * - user clicks on a link
+ *
+ * It's not called when url is changed by $browser.url() method
+ *
+ * The listener gets called with new url as parameter.
+ *
+ * NOTE: this api is intended for use only by the $location service. Please use the
+ * {@link ng.$location $location service} to monitor url changes in angular apps.
+ *
+ * @param {function(string)} listener Listener function to be called when url changes.
+ * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
+ */
+ self.onUrlChange = function(callback) {
+ 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', fireUrlChange);
+ // hashchange event
+ if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
+ // polling
+ else self.addPollFn(fireUrlChange);
+
+ urlChangeInit = true;
+ }
+
+ urlChangeListeners.push(callback);
+ return callback;
+ };
+
+ //////////////////////////////////////////////////////////////
+ // Misc API
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * @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();
+ *
+ * cache.put("key", "value");
+ * cache.put("another key", "another value");
+ *
+ * // We've specified no options on creation
+ * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
+ *
+ *
+ *
+ *
+ * @param {string} cacheId Name or id of the newly created cache.
+ * @param {object=} options Options object that specifies the cache behavior. Properties:
+ *
+ * - `{number=}` `capacity` — turns the cache into LRU cache.
+ *
+ * @returns {object} Newly created cache object with the following set of methods:
+ *
+ * - `{object}` `info()` — Returns id, size, and options of cache.
+ * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
+ * it.
+ * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
+ * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
+ * - `{void}` `removeAll()` — Removes all cached values.
+ * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
+ *
+ */
+function $CacheFactoryProvider() {
+
+ this.$get = function() {
+ var caches = {};
+
+ function cacheFactory(cacheId, options) {
+ if (cacheId in caches) {
+ throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
+ }
+
+ var size = 0,
+ stats = extend({}, options, {id: cacheId}),
+ data = {},
+ capacity = (options && options.capacity) || Number.MAX_VALUE,
+ lruHash = {},
+ freshEnd = null,
+ staleEnd = null;
+
+ return caches[cacheId] = {
+
+ put: function(key, value) {
+ var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
+
+ refresh(lruEntry);
+
+ if (isUndefined(value)) return;
+ if (!(key in data)) size++;
+ data[key] = value;
+
+ if (size > capacity) {
+ this.remove(staleEnd.key);
+ }
+
+ return value;
+ },
+
+
+ get: function(key) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
+
+ refresh(lruEntry);
+
+ return data[key];
+ },
+
+
+ remove: function(key) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
+
+ if (lruEntry == freshEnd) freshEnd = lruEntry.p;
+ if (lruEntry == staleEnd) staleEnd = lruEntry.n;
+ link(lruEntry.n,lruEntry.p);
+
+ delete lruHash[key];
+ delete data[key];
+ size--;
+ },
+
+
+ removeAll: function() {
+ data = {};
+ size = 0;
+ lruHash = {};
+ freshEnd = staleEnd = null;
+ },
+
+
+ destroy: function() {
+ data = null;
+ stats = null;
+ lruHash = null;
+ delete caches[cacheId];
+ },
+
+
+ info: function() {
+ return extend({}, stats, {size: size});
+ }
+ };
+
+
+ /**
+ * makes the `entry` the freshEnd of the LRU linked list
+ */
+ function refresh(entry) {
+ if (entry != freshEnd) {
+ if (!staleEnd) {
+ staleEnd = entry;
+ } else if (staleEnd == entry) {
+ staleEnd = entry.n;
+ }
+
+ link(entry.n, entry.p);
+ link(entry, freshEnd);
+ freshEnd = entry;
+ freshEnd.n = null;
+ }
+ }
+
+
+ /**
+ * bidirectionally links two entries of the LRU linked list
+ */
+ function link(nextEntry, prevEntry) {
+ if (nextEntry != prevEntry) {
+ if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
+ if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
+ }
+ }
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name ng.$cacheFactory#info
+ * @methodOf ng.$cacheFactory
+ *
+ * @description
+ * Get information about all the of the caches that have been created
+ *
+ * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
+ */
+ cacheFactory.info = function() {
+ var info = {};
+ forEach(caches, function(cache, cacheId) {
+ info[cacheId] = cache.info();
+ });
+ return info;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name ng.$cacheFactory#get
+ * @methodOf ng.$cacheFactory
+ *
+ * @description
+ * Get access to a cache object by the `cacheId` used when it was created.
+ *
+ * @param {string} cacheId Name or id of a cache to access.
+ * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
+ */
+ cacheFactory.get = function(cacheId) {
+ return caches[cacheId];
+ };
+
+
+ return cacheFactory;
+ };
+}
+
+/**
+ * @ngdoc object
+ * @name ng.$templateCache
+ *
+ * @description
+ * The first time a template is used, it is loaded in the template cache for quick retrieval. You
+ * can load templates directly into the cache in a `script` tag, or by consuming the
+ * `$templateCache` service directly.
+ *
+ * Adding via the `script` tag:
+ * + * + * + * + * + * ... + * + *+ * + * **Note:** the `script` tag containing the template does not need to be included in the `head` of + * 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:
+ * + * + *+ * + * or get it via Javascript: + *
+ * $templateCache.get('templateId.html')
+ *
+ *
+ * See {@link ng.$cacheFactory $cacheFactory}.
+ *
+ */
+function $TemplateCacheProvider() {
+ this.$get = ['$cacheFactory', function($cacheFactory) {
+ return $cacheFactory('templates');
+ }];
+}
+
+/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
+ *
+ * DOM-related variables:
+ *
+ * - "node" - DOM Node
+ * - "element" - DOM Element or Node
+ * - "$node" or "$element" - jqLite-wrapped node or element
+ *
+ *
+ * Compiler related stuff:
+ *
+ * - "linkFn" - linking fn of a single directive
+ * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
+ * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node
+ * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
+ */
+
+
+/**
+ * @ngdoc function
+ * @name ng.$compile
+ * @function
+ *
+ * @description
+ * Compiles a piece of 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#methods_directive directives}.
+ *
+ *
+ * var myModule = angular.module(...);
+ *
+ * myModule.directive('directiveName', function factory(injectables) {
+ * var directiveDefinitionObject = {
+ * priority: 0,
+ * template: '', // or // function(tElement, tAttrs) { ... },
+ * // or
+ * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
+ * replace: false,
+ * transclude: false,
+ * restrict: 'A',
+ * scope: false,
+ * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
+ * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
+ * compile: function compile(tElement, tAttrs, transclude) {
+ * return {
+ * pre: function preLink(scope, iElement, iAttrs, controller) { ... },
+ * post: function postLink(scope, iElement, iAttrs, controller) { ... }
+ * }
+ * // or
+ * // return function postLink( ... ) { ... }
+ * },
+ * // or
+ * // link: {
+ * // pre: function preLink(scope, iElement, iAttrs, controller) { ... },
+ * // post: function postLink(scope, iElement, iAttrs, controller) { ... }
+ * // }
+ * // or
+ * // link: function postLink( ... ) { ... }
+ * };
+ * return directiveDefinitionObject;
+ * });
+ *
+ *
+ *
+ * var myModule = angular.module(...);
+ *
+ * myModule.directive('directiveName', function factory(injectables) {
+ * var directiveDefinitionObject = {
+ * link: function postLink(scope, iElement, iAttrs) { ... }
+ * };
+ * return directiveDefinitionObject;
+ * // or
+ * // return function postLink(scope, iElement, iAttrs) { ... }
+ * });
+ *
+ *
+ *
+ *
+ * ### Directive Definition Object
+ *
+ * The directive definition object provides instructions to the {@link api/ng.$compile
+ * compiler}. The attributes are:
+ *
+ * #### `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
+ * to sort the directives before their `compile` functions get called. Priority is defined as a
+ * number. Directives with greater numerical `priority` are compiled first. The order of directives with
+ * the same priority is undefined. The default priority is `0`.
+ *
+ * #### `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).
+ *
+ * #### `scope`
+ * **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.
+ *
+ * **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.
+ *
+ * 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 compile(tElement, tAttrs, transclude) { ... }
+ *
+ *
+ * The compile function deals with transforming the template DOM. Since most directives do not do
+ * template transformation, it is not used often. Examples that require compile functions are
+ * directives that transform template DOM, such as {@link
+ * api/ng.directive:ngRepeat ngRepeat}, or load the contents
+ * asynchronously, such as {@link api/ngRoute.directive:ngView ngView}. The
+ * compile function takes the following arguments.
+ *
+ * * `tElement` - template element - The element where the directive has been declared. It is
+ * safe to do template transformation on the element and child elements only.
+ *
+ * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
+ * between all directive compile functions.
+ *
+ * * `transclude` - A transclude linking function: `function(scope, cloneLinkingFn)`.
+ *
+ *
+ * function link(scope, iElement, iAttrs, controller) { ... }
+ *
+ *
+ * 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 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
+ * already been linked.
+ *
+ * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
+ * between all directive linking functions.
+ *
+ * * `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.
+ *
+ *
+ *
+ * #### Pre-linking function
+ *
+ * Executed before the child elements are linked. Not safe to do DOM transformation since the
+ * compiler linking function will fail to locate the correct elements for linking.
+ *
+ * #### Post-linking function
+ *
+ * Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.
+ *
+ *
+ * ### Attributes
+ *
+ * The {@link api/ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
+ * `link()` or `compile()` functions. It has a variety of uses.
+ *
+ * accessing *Normalized attribute names:*
+ * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
+ * the attributes object allows for normalized access to
+ * the attributes.
+ *
+ * * *Directive inter-communication:* All directives share the same instance of the attributes
+ * object which allows the directives to use the attributes object as inter directive
+ * communication.
+ *
+ * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
+ * allowing other directives to read the interpolated value.
+ *
+ * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
+ * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
+ * the only way to easily get the actual value because during the linking phase the interpolation
+ * hasn't been evaluated yet and so the value is at this time set to `undefined`.
+ *
+ *
+ * function linkingFn(scope, elm, attrs, ctrl) {
+ * // get the attribute value
+ * console.log(attrs.ngModel);
+ *
+ * // change the attribute
+ * attrs.$set('ngModel', 'new value');
+ *
+ * // observe changes to interpolated attribute
+ * attrs.$observe('ngModel', function(value) {
+ * console.log('ngModel has changed value to ' + value);
+ * });
+ * }
+ *
+ *
+ * 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:
+ *
+ * var templateHTML = angular.element('{{total}}
'),
+ * scope = ....;
+ *
+ * var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {
+ * //attach the clone to DOM document at the right place
+ * });
+ *
+ * //now we have reference to the cloned DOM via `clone`
+ *
+ *
+ *
+ * For information on how the compiler works, see the
+ * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
+ */
+
+var $compileMinErr = minErr('$compile');
+
+/**
+ * @ngdoc service
+ * @name ng.$compileProvider
+ * @function
+ *
+ * @description
+ */
+$CompileProvider.$inject = ['$provide'];
+function $CompileProvider($provide) {
+ var hasDirectives = {},
+ Suffix = 'Directive',
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
+ CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
+ aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
+ imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file):|data:image\//;
+
+ // 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)$/;
+
+ /**
+ * @ngdoc function
+ * @name ng.$compileProvider#directive
+ * @methodOf ng.$compileProvider
+ * @function
+ *
+ * @description
+ * Register a new directive with the compiler.
+ *
+ * @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
+ * {@link guide/directive} for more info.
+ * @returns {ng.$compileProvider} Self for chaining.
+ */
+ this.directive = function registerDirective(name, directiveFactory) {
+ assertNotHasOwnProperty(name, 'directive');
+ if (isString(name)) {
+ assertArg(directiveFactory, 'directiveFactory');
+ if (!hasDirectives.hasOwnProperty(name)) {
+ hasDirectives[name] = [];
+ $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
+ function($injector, $exceptionHandler) {
+ var directives = [];
+ forEach(hasDirectives[name], function(directiveFactory, index) {
+ try {
+ var directive = $injector.invoke(directiveFactory);
+ if (isFunction(directive)) {
+ directive = { compile: valueFn(directive) };
+ } else if (!directive.compile && directive.link) {
+ directive.compile = valueFn(directive.link);
+ }
+ directive.priority = directive.priority || 0;
+ directive.index = index;
+ directive.name = directive.name || name;
+ directive.require = directive.require || (directive.controller && directive.name);
+ directive.restrict = directive.restrict || 'A';
+ directives.push(directive);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ return directives;
+ }]);
+ }
+ hasDirectives[name].push(directiveFactory);
+ } else {
+ forEach(name, reverseParams(registerDirective));
+ }
+ return this;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name ng.$compileProvider#aHrefSanitizationWhitelist
+ * @methodOf ng.$compileProvider
+ * @function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during a[href] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.aHrefSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ aHrefSanitizationWhitelist = regexp;
+ return this;
+ }
+ return aHrefSanitizationWhitelist;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name ng.$compileProvider#imgSrcSanitizationWhitelist
+ * @methodOf ng.$compileProvider
+ * @function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during img[src] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.imgSrcSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ imgSrcSanitizationWhitelist = regexp;
+ return this;
+ }
+ return imgSrcSanitizationWhitelist;
+ };
+
+
+ this.$get = [
+ '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
+ '$controller', '$rootScope', '$document', '$sce', '$animate',
+ function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
+ $controller, $rootScope, $document, $sce, $animate) {
+
+ var Attributes = function(element, attr) {
+ this.$$element = element;
+ this.$attr = attr || {};
+ };
+
+ Attributes.prototype = {
+ $normalize: directiveNormalize,
+
+
+ /**
+ * @ngdoc function
+ * @name ng.$compile.directive.Attributes#$addClass
+ * @methodOf ng.$compile.directive.Attributes
+ * @function
+ *
+ * @description
+ * Adds the CSS class value specified by the classVal parameter to the element. If animations
+ * are enabled then an animation will be triggered for the class addition.
+ *
+ * @param {string} classVal The className value that will be added to the element
+ */
+ $addClass : function(classVal) {
+ if(classVal && classVal.length > 0) {
+ $animate.addClass(this.$$element, classVal);
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name ng.$compile.directive.Attributes#$removeClass
+ * @methodOf ng.$compile.directive.Attributes
+ * @function
+ *
+ * @description
+ * Removes the CSS class value specified by the classVal parameter from the element. If
+ * animations are enabled then an animation will be triggered for the class removal.
+ *
+ * @param {string} classVal The className value that will be removed from the element
+ */
+ $removeClass : function(classVal) {
+ if(classVal && classVal.length > 0) {
+ $animate.removeClass(this.$$element, classVal);
+ }
+ },
+
+ /**
+ * Set a normalized attribute on the element in a way such that all directives
+ * can share the attribute. This function properly handles boolean attributes.
+ * @param {string} key Normalized key. (ie ngAttribute)
+ * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
+ * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
+ * Defaults to true.
+ * @param {string=} attrName Optional none normalized name. Defaults to key.
+ */
+ $set: function(key, value, writeAttr, attrName) {
+ //special case for class attribute addition + removal
+ //so that class changes can tap into the animation
+ //hooks provided by the $animate service
+ if(key == 'class') {
+ value = value || '';
+ var current = this.$$element.attr('class') || '';
+ this.$removeClass(tokenDifference(current, value).join(' '));
+ this.$addClass(tokenDifference(value, current).join(' '));
+ } else {
+ var booleanKey = getBooleanAttrName(this.$$element[0], key),
+ normalizedVal,
+ nodeName;
+
+ if (booleanKey) {
+ this.$$element.prop(key, value);
+ attrName = booleanKey;
+ }
+
+ this[key] = value;
+
+ // translate normalized key to actual key
+ if (attrName) {
+ this.$attr[key] = attrName;
+ } else {
+ attrName = this.$attr[key];
+ if (!attrName) {
+ this.$attr[key] = attrName = snake_case(key, '-');
+ }
+ }
+
+ nodeName = nodeName_(this.$$element);
+
+ // sanitize a[href] and img[src] values
+ if ((nodeName === 'A' && key === 'href') ||
+ (nodeName === 'IMG' && key === 'src')) {
+ // NOTE: urlResolve() doesn't support IE < 8 so we don't sanitize for that case.
+ if (!msie || msie >= 8 ) {
+ normalizedVal = urlResolve(value).href;
+ if (normalizedVal !== '') {
+ if ((key === 'href' && !normalizedVal.match(aHrefSanitizationWhitelist)) ||
+ (key === 'src' && !normalizedVal.match(imgSrcSanitizationWhitelist))) {
+ this[key] = value = 'unsafe:' + normalizedVal;
+ }
+ }
+ }
+ }
+
+ if (writeAttr !== false) {
+ if (value === null || value === undefined) {
+ this.$$element.removeAttr(attrName);
+ } else {
+ this.$$element.attr(attrName, value);
+ }
+ }
+ }
+
+ // fire observers
+ var $$observers = this.$$observers;
+ $$observers && forEach($$observers[key], function(fn) {
+ try {
+ fn(value);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+
+ function tokenDifference(str1, str2) {
+ var values = [],
+ tokens1 = str1.split(/\s+/),
+ tokens2 = str2.split(/\s+/);
+
+ outer:
+ for(var i=0;i
+ * 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.
+ *
+ * @param {Error} exception Exception associated with the error.
+ * @param {string=} cause optional information about the context in which
+ * the error was thrown.
+ *
+ */
+function $ExceptionHandlerProvider() {
+ this.$get = ['$log', function($log) {
+ return function(exception, cause) {
+ $log.error.apply($log, arguments);
+ };
+ }];
+}
+
+/**
+ * Parse headers into key value object
+ *
+ * @param {string} headers Raw headers as a string
+ * @returns {Object} Parsed headers as key value object
+ */
+function parseHeaders(headers) {
+ var parsed = {}, key, val, i;
+
+ if (!headers) return parsed;
+
+ forEach(headers.split('\n'), function(line) {
+ i = line.indexOf(':');
+ key = lowercase(trim(line.substr(0, i)));
+ val = trim(line.substr(i + 1));
+
+ if (key) {
+ if (parsed[key]) {
+ parsed[key] += ', ' + val;
+ } else {
+ parsed[key] = val;
+ }
+ }
+ });
+
+ return parsed;
+}
+
+
+/**
+ * Returns a function that provides access to parsed headers.
+ *
+ * Headers are lazy parsed when first requested.
+ * @see parseHeaders
+ *
+ * @param {(string|Object)} headers Headers to provide access to.
+ * @returns {function(string=)} Returns a getter function which if called with:
+ *
+ * - if called with single an argument returns a single header value or null
+ * - if called with no arguments returns an object containing all headers.
+ */
+function headersGetter(headers) {
+ var headersObj = isObject(headers) ? headers : undefined;
+
+ return function(name) {
+ if (!headersObj) headersObj = parseHeaders(headers);
+
+ if (name) {
+ return headersObj[lowercase(name)] || null;
+ }
+
+ return headersObj;
+ };
+}
+
+
+/**
+ * Chain all given functions
+ *
+ * This function is used for both request and response transforming
+ *
+ * @param {*} data Data to transform.
+ * @param {function(string=)} headers Http headers getter fn.
+ * @param {(function|Array.
+ * $http({method: 'GET', url: '/someUrl'}).
+ * success(function(data, status, headers, config) {
+ * // this callback will be called asynchronously
+ * // when the response is available
+ * }).
+ * error(function(data, status, headers, config) {
+ * // called asynchronously if an error occurs
+ * // or server returns response with an error status.
+ * });
+ *
+ *
+ * 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.
+ *
+ * ```
+ * $scope.$apply(function() {
+ * $http(...);
+ * });
+ * ```
+ *
+ * # 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(...);
+ * $scope.$apply(function() {
+ * $http.get(...);
+ * });
+ * $httpBackend.flush();
+ * ```
+ *
+ * # Shortcut methods
+ *
+ * Since all invocations of the $http service require passing in an HTTP method and URL, and
+ * POST/PUT requests require request data to be provided as well, shortcut methods
+ * were created:
+ *
+ *
+ * $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
+ * object, which currently contains this default configuration:
+ *
+ * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
+ * - `Accept: application/json, text/plain, * / *`
+ * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
+ * - `Content-Type: application/json`
+ * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
+ * - `Content-Type: application/json`
+ *
+ * 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' }.
+ *
+ * The defaults can also be set at runtime via the `$http.defaults` object in the same
+ * fashion. 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.
+ *
+ *
+ * # Transforming Requests and Responses
+ *
+ * Both requests and responses can be transformed using transform functions. By default, Angular
+ * applies these transformations:
+ *
+ * Request transformations:
+ *
+ * - If the `data` property of the request configuration object contains an object, serialize it
+ * into JSON format.
+ *
+ * Response transformations:
+ *
+ * - If XSRF prefix is detected, strip it (see Security Considerations section below).
+ * - If JSON response is detected, deserialize it using a JSON parser.
+ *
+ * To globally augment or override the default transforms, modify the
+ * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse`
+ * properties. These properties are by default an array of transform functions, which allows you
+ * to `push` or `unshift` a new transformation function into the transformation chain. You can
+ * also decide to completely override any default transformations by assigning your
+ * transformation functions to these properties directly without the array wrapper.
+ *
+ * Similarly, to locally override the request/response transforms, augment the
+ * `transformRequest` and/or `transformResponse` properties of the configuration object passed
+ * into `$http`.
+ *
+ *
+ * # Caching
+ *
+ * To enable caching, set the configuration property `cache` to `true`. When the cache is
+ * enabled, `$http` stores the response from the server in local cache. Next time the
+ * response is served from the cache without sending a request to the server.
+ *
+ * Note that even if the response is served from cache, delivery of the data is asynchronous in
+ * the same way that real requests are.
+ *
+ * If there are multiple GET requests for the same URL that should be cached using the same
+ * cache, but the cache is not populated yet, only one request to the server will be made and
+ * the remaining requests will be fulfilled using the response from the first request.
+ *
+ * A custom default cache built with $cacheFactory can be provided in $http.defaults.cache.
+ * To skip it, set configuration property `cache` to `false`.
+ *
+ *
+ * # Interceptors
+ *
+ * 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 pre-processing of request or postprocessing of responses, it is desirable to be
+ * able to intercept requests before they are handed to the server and
+ * responses before they are handed over to the application code that
+ * initiated these requests. The interceptors leverage the {@link ng.$q
+ * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
+ *
+ * The interceptors are service factories that are registered with the `$httpProvider` by
+ * adding them to the `$httpProvider.interceptors` array. The factory is called and
+ * injected with dependencies (if specified) and returns the interceptor.
+ *
+ * There are two kinds of interceptors (and two kinds of rejection interceptors):
+ *
+ * * `request`: interceptors get called with http `config` object. The function is free to
+ * modify the `config` or create a new one. The function needs to return the `config`
+ * directly or as a promise.
+ * * `requestError`: interceptor gets called when a previous interceptor threw an error or
+ * resolved with a rejection.
+ * * `response`: interceptors get called with http `response` object. The function is free to
+ * modify the `response` or create a new one. The function needs to return the `response`
+ * directly or as a promise.
+ * * `responseError`: interceptor gets called when a previous interceptor threw an error or
+ * resolved with a rejection.
+ *
+ *
+ *
+ * // 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 || $q.when(config);
+ * },
+ *
+ * // optional method
+ * 'requestError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * },
+ *
+ *
+ *
+ * // optional method
+ * 'response': function(response) {
+ * // do something on success
+ * return response || $q.when(response);
+ * },
+ *
+ * // optional method
+ * 'responseError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * };
+ * }
+ * });
+ *
+ * $httpProvider.interceptors.push('myHttpInterceptor');
+ *
+ *
+ * // register the interceptor via an anonymous factory
+ * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
+ * return {
+ * 'request': function(config) {
+ * // same as above
+ * },
+ * 'response': function(response) {
+ * // same as above
+ * }
+ * };
+ * });
+ *
+ *
+ * # 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:
+ *
+ * - {@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
+ *
+ * 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:
+ * + * ['one','two'] + *+ * + * which is vulnerable to attack, your server can return: + *
+ * )]}', + * ['one','two'] + *+ * + * Angular will strip the prefix, before processing the JSON. + * + * + * ## Cross Site Request Forgery (XSRF) Protection + * + * {@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 + * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure + * 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 {@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, or the per-request config object. + * + * + * @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.