summaryrefslogtreecommitdiffstats
path: root/afb-client/bower_components/angular
diff options
context:
space:
mode:
Diffstat (limited to 'afb-client/bower_components/angular')
-rw-r--r--afb-client/bower_components/angular/.bower.json17
-rw-r--r--afb-client/bower_components/angular/README.md64
-rw-r--r--afb-client/bower_components/angular/angular-csp.css13
-rw-r--r--afb-client/bower_components/angular/angular.js26451
-rw-r--r--afb-client/bower_components/angular/angular.min.js253
-rw-r--r--afb-client/bower_components/angular/angular.min.js.gzipbin0 -> 46451 bytes
-rw-r--r--afb-client/bower_components/angular/angular.min.js.map8
-rw-r--r--afb-client/bower_components/angular/bower.json8
-rw-r--r--afb-client/bower_components/angular/index.js2
-rw-r--r--afb-client/bower_components/angular/package.json25
10 files changed, 26841 insertions, 0 deletions
diff --git a/afb-client/bower_components/angular/.bower.json b/afb-client/bower_components/angular/.bower.json
new file mode 100644
index 0000000..1b094cf
--- /dev/null
+++ b/afb-client/bower_components/angular/.bower.json
@@ -0,0 +1,17 @@
+{
+ "name": "angular",
+ "version": "1.3.20",
+ "main": "./angular.js",
+ "ignore": [],
+ "dependencies": {},
+ "homepage": "https://github.com/angular/bower-angular",
+ "_release": "1.3.20",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.3.20",
+ "commit": "0cd10f27471310fe07167b00f8a4242c6bba4df2"
+ },
+ "_source": "git://github.com/angular/bower-angular.git",
+ "_target": "~1.3.4",
+ "_originalSource": "angular"
+} \ No newline at end of file
diff --git a/afb-client/bower_components/angular/README.md b/afb-client/bower_components/angular/README.md
new file mode 100644
index 0000000..d1bc0ed
--- /dev/null
+++ b/afb-client/bower_components/angular/README.md
@@ -0,0 +1,64 @@
+# packaged angular
+
+This repo is for distribution on `npm` and `bower`. The source for this module is in the
+[main AngularJS repo](https://github.com/angular/angular.js).
+Please file issues and pull requests against that repo.
+
+## Install
+
+You can install this package either with `npm` or with `bower`.
+
+### npm
+
+```shell
+npm install angular
+```
+
+Then add a `<script>` to your `index.html`:
+
+```html
+<script src="/node_modules/angular/angular.js"></script>
+```
+
+Or `require('angular')` from your code.
+
+### bower
+
+```shell
+bower install angular
+```
+
+Then add a `<script>` to your `index.html`:
+
+```html
+<script src="/bower_components/angular/angular.js"></script>
+```
+
+## Documentation
+
+Documentation is available on the
+[AngularJS docs site](http://docs.angularjs.org/).
+
+## License
+
+The MIT License
+
+Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/afb-client/bower_components/angular/angular-csp.css b/afb-client/bower_components/angular/angular-csp.css
new file mode 100644
index 0000000..0ce9d86
--- /dev/null
+++ b/afb-client/bower_components/angular/angular-csp.css
@@ -0,0 +1,13 @@
+/* Include this file in your html if you are using the CSP mode. */
+
+@charset "UTF-8";
+
+[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
+.ng-cloak, .x-ng-cloak,
+.ng-hide:not(.ng-hide-animate) {
+ display: none !important;
+}
+
+ng\:form {
+ display: block;
+}
diff --git a/afb-client/bower_components/angular/angular.js b/afb-client/bower_components/angular/angular.js
new file mode 100644
index 0000000..2445ab5
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.js
@@ -0,0 +1,26451 @@
+/**
+ * @license AngularJS v1.3.20
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, document, undefined) {'use strict';
+
+/**
+ * @description
+ *
+ * This object provides a utility for producing rich Error messages within
+ * Angular. It can be called as follows:
+ *
+ * var exampleMinErr = minErr('example');
+ * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
+ *
+ * The above creates an instance of minErr in the example namespace. The
+ * resulting error will have a namespaced error code of example.one. The
+ * resulting error will replace {0} with the value of foo, and {1} with the
+ * value of bar. The object is not restricted in the number of arguments it can
+ * take.
+ *
+ * If fewer arguments are specified than necessary for interpolation, the extra
+ * interpolation markers will be preserved in the final string.
+ *
+ * Since data will be parsed statically during a build step, some restrictions
+ * are applied with respect to how minErr instances are created and called.
+ * Instances should have names of the form namespaceMinErr for a minErr created
+ * using minErr('namespace') . Error codes, namespaces and template strings
+ * should all be static strings, not variables or general expressions.
+ *
+ * @param {string} module The namespace to use for the new minErr instance.
+ * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
+ * error from returned function, for cases when a particular type of error is useful.
+ * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
+ */
+
+function minErr(module, ErrorConstructor) {
+ ErrorConstructor = ErrorConstructor || Error;
+ return function() {
+ var code = arguments[0],
+ prefix = '[' + (module ? module + ':' : '') + code + '] ',
+ template = arguments[1],
+ templateArgs = arguments,
+
+ message, i;
+
+ message = prefix + template.replace(/\{\d+\}/g, function(match) {
+ var index = +match.slice(1, -1), arg;
+
+ if (index + 2 < templateArgs.length) {
+ return toDebugString(templateArgs[index + 2]);
+ }
+ return match;
+ });
+
+ message = message + '\nhttp://errors.angularjs.org/1.3.20/' +
+ (module ? module + '/' : '') + code;
+ for (i = 2; i < arguments.length; i++) {
+ message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
+ encodeURIComponent(toDebugString(arguments[i]));
+ }
+ return new ErrorConstructor(message);
+ };
+}
+
+/* We need to tell jshint what variables are being exported */
+/* global angular: true,
+ msie: true,
+ jqLite: true,
+ jQuery: true,
+ slice: true,
+ splice: true,
+ push: true,
+ toString: true,
+ ngMinErr: true,
+ angularModule: true,
+ uid: true,
+ REGEX_STRING_REGEXP: true,
+ VALIDITY_STATE_PROPERTY: true,
+
+ lowercase: true,
+ uppercase: true,
+ manualLowercase: true,
+ manualUppercase: true,
+ nodeName_: true,
+ isArrayLike: true,
+ forEach: true,
+ sortedKeys: true,
+ forEachSorted: true,
+ reverseParams: true,
+ nextUid: true,
+ setHashKey: true,
+ extend: true,
+ int: true,
+ inherit: true,
+ noop: true,
+ identity: true,
+ valueFn: true,
+ isUndefined: true,
+ isDefined: true,
+ isObject: true,
+ isString: true,
+ isNumber: true,
+ isDate: true,
+ isArray: true,
+ isFunction: true,
+ isRegExp: true,
+ isWindow: true,
+ isScope: true,
+ isFile: true,
+ isFormData: true,
+ isBlob: true,
+ isBoolean: true,
+ isPromiseLike: true,
+ trim: true,
+ escapeForRegexp: true,
+ isElement: true,
+ makeMap: true,
+ includes: true,
+ arrayRemove: true,
+ copy: true,
+ shallowCopy: true,
+ equals: true,
+ csp: true,
+ concat: true,
+ sliceArgs: true,
+ bind: true,
+ toJsonReplacer: true,
+ toJson: true,
+ fromJson: true,
+ startingTag: true,
+ tryDecodeURIComponent: true,
+ parseKeyValue: true,
+ toKeyValue: true,
+ encodeUriSegment: true,
+ encodeUriQuery: true,
+ angularInit: true,
+ bootstrap: true,
+ getTestability: true,
+ snake_case: true,
+ bindJQuery: true,
+ assertArg: true,
+ assertArgFn: true,
+ assertNotHasOwnProperty: true,
+ getter: true,
+ getBlockNodes: true,
+ hasOwnProperty: true,
+ createMap: true,
+
+ NODE_TYPE_ELEMENT: true,
+ NODE_TYPE_ATTRIBUTE: true,
+ NODE_TYPE_TEXT: true,
+ NODE_TYPE_COMMENT: true,
+ NODE_TYPE_DOCUMENT: true,
+ NODE_TYPE_DOCUMENT_FRAGMENT: true,
+*/
+
+////////////////////////////////////
+
+/**
+ * @ngdoc module
+ * @name ng
+ * @module ng
+ * @description
+ *
+ * # ng (core module)
+ * The ng module is loaded by default when an AngularJS application is started. The module itself
+ * contains the essential components for an AngularJS application to function. The table below
+ * lists a high level breakdown of each of the services/factories, filters, directives and testing
+ * components available within this core module.
+ *
+ * <div doc-module-components="ng"></div>
+ */
+
+var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
+
+// The name of a form control's ValidityState property.
+// This is used so that it's possible for internal tests to create mock ValidityStates.
+var VALIDITY_STATE_PROPERTY = 'validity';
+
+/**
+ * @ngdoc function
+ * @name angular.lowercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to lowercase.
+ * @param {string} string String to be converted to lowercase.
+ * @returns {string} Lowercased string.
+ */
+var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/**
+ * @ngdoc function
+ * @name angular.uppercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to uppercase.
+ * @param {string} string String to be converted to uppercase.
+ * @returns {string} Uppercased string.
+ */
+var 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
+ msie, // holds major version number for IE, or NaN if UA is not IE.
+ jqLite, // delay binding since jQuery could be loaded after us.
+ jQuery, // delay binding
+ slice = [].slice,
+ splice = [].splice,
+ push = [].push,
+ toString = Object.prototype.toString,
+ ngMinErr = minErr('ng'),
+
+ /** @name angular */
+ angular = window.angular || (window.angular = {}),
+ angularModule,
+ uid = 0;
+
+/**
+ * documentMode is an IE-only property
+ * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
+ */
+msie = document.documentMode;
+
+
+/**
+ * @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;
+ }
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // "length" in obj used to prevent JIT error (gh-11508)
+ var length = "length" in Object(obj) && obj.length;
+
+ if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
+ return true;
+ }
+
+ return isString(obj) || isArray(obj) || length === 0 ||
+ typeof length === 'number' && length > 0 && (length - 1) in obj;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.forEach
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
+ * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
+ * is the value of an object property or an array element, `key` is the object property key or
+ * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
+ *
+ * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
+ * using the `hasOwnProperty` method.
+ *
+ * Unlike ES262's
+ * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
+ * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
+ * return the value provided.
+ *
+ ```js
+ var values = {name: 'misko', gender: 'male'};
+ var log = [];
+ angular.forEach(values, function(value, key) {
+ 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, length;
+ if (obj) {
+ if (isFunction(obj)) {
+ for (key in obj) {
+ // Need to check if hasOwnProperty exists,
+ // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
+ if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } else if (isArray(obj) || isArrayLike(obj)) {
+ var isPrimitive = typeof obj !== 'object';
+ for (key = 0, length = obj.length; key < length; key++) {
+ if (isPrimitive || key in obj) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } else if (obj.forEach && obj.forEach !== forEach) {
+ obj.forEach(iterator, context, obj);
+ } else {
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ }
+ }
+ return obj;
+}
+
+function sortedKeys(obj) {
+ return Object.keys(obj).sort();
+}
+
+function forEachSorted(obj, iterator, context) {
+ var keys = sortedKeys(obj);
+ 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.
+ *
+ * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
+ * we hit number precision issues in JavaScript.
+ *
+ * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
+ *
+ * @returns {number} an unique alpha-numeric string
+ */
+function nextUid() {
+ return ++uid;
+}
+
+
+/**
+ * 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
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
+ * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
+ * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
+ * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).
+ *
+ * @param {Object} dst Destination object.
+ * @param {...Object} src Source object(s).
+ * @returns {Object} Reference to `dst`.
+ */
+function extend(dst) {
+ var h = dst.$$hashKey;
+
+ for (var i = 1, ii = arguments.length; i < ii; i++) {
+ var obj = arguments[i];
+ if (obj) {
+ var keys = Object.keys(obj);
+ for (var j = 0, jj = keys.length; j < jj; j++) {
+ var key = keys[j];
+ dst[key] = obj[key];
+ }
+ }
+ }
+
+ setHashKey(dst, h);
+ return dst;
+}
+
+function int(str) {
+ return parseInt(str, 10);
+}
+
+
+function inherit(parent, extra) {
+ return extend(Object.create(parent), extra);
+}
+
+/**
+ * @ngdoc function
+ * @name angular.noop
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * A function that performs no operations. This function can be useful when writing code in the
+ * functional style.
+ ```js
+ function foo(callback) {
+ var result = calculateResult();
+ (callback || angular.noop)(result);
+ }
+ ```
+ */
+function noop() {}
+noop.$inject = [];
+
+
+/**
+ * @ngdoc function
+ * @name angular.identity
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * A function that returns its first argument. This function is useful when writing code in the
+ * functional style.
+ *
+ ```js
+ function transformer(transformationFn, value) {
+ return (transformationFn || angular.identity)(value);
+ };
+ ```
+ * @param {*} value to be returned.
+ * @returns {*} the value passed in.
+ */
+function identity($) {return $;}
+identity.$inject = [];
+
+
+function valueFn(value) {return function() {return value;};}
+
+/**
+ * @ngdoc function
+ * @name angular.isUndefined
+ * @module ng
+ * @kind 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
+ * @module ng
+ * @kind 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
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
+ * considered to be objects. Note that JavaScript arrays are objects.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Object` but not `null`.
+ */
+function isObject(value) {
+ // http://jsperf.com/isobject4
+ return value !== null && typeof value === 'object';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isString
+ * @module ng
+ * @kind 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
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a `Number`.
+ *
+ * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
+ *
+ * If you wish to exclude these then you can use the native
+ * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
+ * method.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Number`.
+ */
+function isNumber(value) {return typeof value === 'number';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDate
+ * @module ng
+ * @kind 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.call(value) === '[object Date]';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isArray
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is an `Array`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Array`.
+ */
+var isArray = Array.isArray;
+
+/**
+ * @ngdoc function
+ * @name angular.isFunction
+ * @module ng
+ * @kind 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.call(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.window === obj;
+}
+
+
+function isScope(obj) {
+ return obj && obj.$evalAsync && obj.$watch;
+}
+
+
+function isFile(obj) {
+ return toString.call(obj) === '[object File]';
+}
+
+
+function isFormData(obj) {
+ return toString.call(obj) === '[object FormData]';
+}
+
+
+function isBlob(obj) {
+ return toString.call(obj) === '[object Blob]';
+}
+
+
+function isBoolean(value) {
+ return typeof value === 'boolean';
+}
+
+
+function isPromiseLike(obj) {
+ return obj && isFunction(obj.then);
+}
+
+
+var trim = function(value) {
+ return isString(value) ? value.trim() : value;
+};
+
+// Copied from:
+// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
+// Prereq: s is a string.
+var escapeForRegexp = function(s) {
+ return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
+ replace(/\x08/g, '\\x08');
+};
+
+
+/**
+ * @ngdoc function
+ * @name angular.isElement
+ * @module ng
+ * @kind 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.prop && node.attr && 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;
+}
+
+
+function nodeName_(element) {
+ return lowercase(element.nodeName || (element[0] && element[0].nodeName));
+}
+
+function includes(array, obj) {
+ return Array.prototype.indexOf.call(array, obj) != -1;
+}
+
+function arrayRemove(array, value) {
+ var index = array.indexOf(value);
+ if (index >= 0)
+ array.splice(index, 1);
+ return value;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.copy
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Creates a deep copy of `source`, which should be an object or an array.
+ *
+ * * If no destination is supplied, a copy of the object or array is created.
+ * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
+ * 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
+ <example module="copyExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form novalidate class="simple-form">
+ Name: <input type="text" ng-model="user.name" /><br />
+ E-mail: <input type="email" ng-model="user.email" /><br />
+ Gender: <input type="radio" ng-model="user.gender" value="male" />male
+ <input type="radio" ng-model="user.gender" value="female" />female<br />
+ <button ng-click="reset()">RESET</button>
+ <button ng-click="update(user)">SAVE</button>
+ </form>
+ <pre>form = {{user | json}}</pre>
+ <pre>master = {{master | json}}</pre>
+ </div>
+
+ <script>
+ angular.module('copyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.master= {};
+
+ $scope.update = function(user) {
+ // Example with 1 argument
+ $scope.master= angular.copy(user);
+ };
+
+ $scope.reset = function() {
+ // Example with 2 arguments
+ angular.copy($scope.master, $scope.user);
+ };
+
+ $scope.reset();
+ }]);
+ </script>
+ </file>
+ </example>
+ */
+function copy(source, destination, stackSource, stackDest) {
+ if (isWindow(source) || isScope(source)) {
+ throw ngMinErr('cpws',
+ "Can't copy! Making copies of Window or Scope instances is not supported.");
+ }
+
+ if (!destination) {
+ destination = source;
+ if (source) {
+ if (isArray(source)) {
+ destination = copy(source, [], stackSource, stackDest);
+ } else if (isDate(source)) {
+ destination = new Date(source.getTime());
+ } else if (isRegExp(source)) {
+ destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
+ destination.lastIndex = source.lastIndex;
+ } else if (isObject(source)) {
+ var emptyObject = Object.create(Object.getPrototypeOf(source));
+ destination = copy(source, emptyObject, stackSource, stackDest);
+ }
+ }
+ } else {
+ if (source === destination) throw ngMinErr('cpi',
+ "Can't copy! Source and destination are identical.");
+
+ stackSource = stackSource || [];
+ stackDest = stackDest || [];
+
+ if (isObject(source)) {
+ var index = stackSource.indexOf(source);
+ if (index !== -1) return stackDest[index];
+
+ stackSource.push(source);
+ stackDest.push(destination);
+ }
+
+ var result;
+ if (isArray(source)) {
+ destination.length = 0;
+ for (var i = 0; i < source.length; i++) {
+ result = copy(source[i], null, stackSource, stackDest);
+ if (isObject(source[i])) {
+ stackSource.push(source[i]);
+ stackDest.push(result);
+ }
+ destination.push(result);
+ }
+ } else {
+ var h = destination.$$hashKey;
+ if (isArray(destination)) {
+ destination.length = 0;
+ } else {
+ forEach(destination, function(value, key) {
+ delete destination[key];
+ });
+ }
+ for (var key in source) {
+ if (source.hasOwnProperty(key)) {
+ result = copy(source[key], null, stackSource, stackDest);
+ if (isObject(source[key])) {
+ stackSource.push(source[key]);
+ stackDest.push(result);
+ }
+ destination[key] = result;
+ }
+ }
+ setHashKey(destination,h);
+ }
+
+ }
+ return destination;
+}
+
+/**
+ * Creates a shallow copy of an object, an array or a primitive.
+ *
+ * Assumes that there are no proto properties for objects.
+ */
+function shallowCopy(src, dst) {
+ if (isArray(src)) {
+ dst = dst || [];
+
+ for (var i = 0, ii = src.length; i < ii; i++) {
+ dst[i] = src[i];
+ }
+ } else if (isObject(src)) {
+ dst = dst || {};
+
+ for (var key in src) {
+ if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
+ dst[key] = src[key];
+ }
+ }
+ }
+
+ return dst || src;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.equals
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if two objects or two values are equivalent. Supports value types, regular
+ * expressions, arrays and objects.
+ *
+ * Two objects or values are considered equivalent if at least one of the following is true:
+ *
+ * * Both objects or values pass `===` comparison.
+ * * Both objects or values are of the same type and all of their properties are equal by
+ * comparing them with `angular.equals`.
+ * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
+ * * Both values represent the same regular expression (In JavaScript,
+ * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
+ * representation matches).
+ *
+ * During a property comparison, properties of `function` type and properties with names
+ * that begin with `$` are ignored.
+ *
+ * Scope and DOMWindow objects are being compared only by identify (`===`).
+ *
+ * @param {*} o1 Object or value to compare.
+ * @param {*} o2 Object or value to compare.
+ * @returns {boolean} True if arguments are equal.
+ */
+function equals(o1, o2) {
+ if (o1 === o2) return true;
+ if (o1 === null || o2 === null) return false;
+ if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
+ var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
+ if (t1 == t2) {
+ if (t1 == 'object') {
+ if (isArray(o1)) {
+ if (!isArray(o2)) return false;
+ if ((length = o1.length) == o2.length) {
+ for (key = 0; key < length; key++) {
+ if (!equals(o1[key], o2[key])) return false;
+ }
+ return true;
+ }
+ } else if (isDate(o1)) {
+ if (!isDate(o2)) return false;
+ return equals(o1.getTime(), o2.getTime());
+ } else if (isRegExp(o1)) {
+ return isRegExp(o2) ? o1.toString() == o2.toString() : false;
+ } else {
+ if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
+ isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
+ keySet = {};
+ for (key in o1) {
+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+ if (!equals(o1[key], o2[key])) return false;
+ keySet[key] = true;
+ }
+ for (key in o2) {
+ if (!keySet.hasOwnProperty(key) &&
+ key.charAt(0) !== '$' &&
+ o2[key] !== undefined &&
+ !isFunction(o2[key])) return false;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+var csp = function() {
+ if (isDefined(csp.isActive_)) return csp.isActive_;
+
+ var active = !!(document.querySelector('[ng-csp]') ||
+ document.querySelector('[data-ng-csp]'));
+
+ if (!active) {
+ try {
+ /* jshint -W031, -W054 */
+ new Function('');
+ /* jshint +W031, +W054 */
+ } catch (e) {
+ active = true;
+ }
+ }
+
+ return (csp.isActive_ = active);
+};
+
+
+
+function concat(array1, array2, index) {
+ return array1.concat(slice.call(array2, index));
+}
+
+function sliceArgs(args, startIndex) {
+ return slice.call(args, startIndex || 0);
+}
+
+
+/* jshint -W101 */
+/**
+ * @ngdoc function
+ * @name angular.bind
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
+ * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
+ * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
+ * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
+ *
+ * @param {Object} self Context which `fn` should be evaluated in.
+ * @param {function()} fn Function to be bound.
+ * @param {...*} args Optional arguments to be prebound to the `fn` function call.
+ * @returns {function()} Function that wraps the `fn` with all the specified bindings.
+ */
+/* jshint +W101 */
+function bind(self, fn) {
+ var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
+ if (isFunction(fn) && !(fn instanceof RegExp)) {
+ return curryArgs.length
+ ? function() {
+ return arguments.length
+ ? fn.apply(self, concat(curryArgs, arguments, 0))
+ : fn.apply(self, curryArgs);
+ }
+ : function() {
+ return arguments.length
+ ? fn.apply(self, arguments)
+ : fn.call(self);
+ };
+ } else {
+ // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
+ return fn;
+ }
+}
+
+
+function toJsonReplacer(key, value) {
+ var val = value;
+
+ if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
+ val = undefined;
+ } else if (isWindow(value)) {
+ val = '$WINDOW';
+ } else if (value && document === value) {
+ val = '$DOCUMENT';
+ } else if (isScope(value)) {
+ val = '$SCOPE';
+ }
+
+ return val;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.toJson
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
+ * stripped since angular uses this notation internally.
+ *
+ * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
+ * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
+ * If set to an integer, the JSON output will contain that many spaces per indentation.
+ * @returns {string|undefined} JSON-ified string representing `obj`.
+ */
+function toJson(obj, pretty) {
+ if (typeof obj === 'undefined') return undefined;
+ if (!isNumber(pretty)) {
+ pretty = pretty ? 2 : null;
+ }
+ return JSON.stringify(obj, toJsonReplacer, pretty);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.fromJson
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Deserializes a JSON string.
+ *
+ * @param {string} json JSON string to deserialize.
+ * @returns {Object|Array|string|number} Deserialized JSON string.
+ */
+function fromJson(json) {
+ return isString(json)
+ ? JSON.parse(json)
+ : json;
+}
+
+
+/**
+ * @returns {string} Returns the string representation of the element.
+ */
+function startingTag(element) {
+ element = jqLite(element).clone();
+ try {
+ // turns out IE does not let you set .html() on elements which
+ // are not allowed to have children. So we just ignore it.
+ element.empty();
+ } catch (e) {}
+ var elemHtml = jqLite('<div>').append(element).html();
+ try {
+ return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
+ elemHtml.
+ match(/^(<[^>]+>)/)[1].
+ replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ } catch (e) {
+ return lowercase(elemHtml);
+ }
+
+}
+
+
+/////////////////////////////////////////////////
+
+/**
+ * Tries to decode the URI component without throwing an exception.
+ *
+ * @private
+ * @param str value potential URI component to check.
+ * @returns {boolean} True if `value` can be decoded
+ * with the decodeURIComponent function.
+ */
+function tryDecodeURIComponent(value) {
+ try {
+ return decodeURIComponent(value);
+ } catch (e) {
+ // Ignore any invalid uri component
+ }
+}
+
+
+/**
+ * Parses an escaped url query string into key-value pairs.
+ * @returns {Object.<string,boolean|Array>}
+ */
+function parseKeyValue(/**string*/keyValue) {
+ var obj = {}, key_value, key;
+ forEach((keyValue || "").split('&'), function(keyValue) {
+ if (keyValue) {
+ key_value = keyValue.replace(/\+/g,'%20').split('=');
+ key = tryDecodeURIComponent(key_value[0]);
+ if (isDefined(key)) {
+ var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
+ if (!hasOwnProperty.call(obj, key)) {
+ obj[key] = val;
+ } else if (isArray(obj[key])) {
+ obj[key].push(val);
+ } else {
+ obj[key] = [obj[key],val];
+ }
+ }
+ }
+ });
+ return obj;
+}
+
+function toKeyValue(obj) {
+ var parts = [];
+ forEach(obj, function(value, key) {
+ if (isArray(value)) {
+ forEach(value, function(arrayValue) {
+ parts.push(encodeUriQuery(key, true) +
+ (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
+ });
+ } else {
+ parts.push(encodeUriQuery(key, true) +
+ (value === true ? '' : '=' + encodeUriQuery(value, true)));
+ }
+ });
+ return parts.length ? parts.join('&') : '';
+}
+
+
+/**
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+ * segments:
+ * segment = *pchar
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriSegment(val) {
+ return encodeUriQuery(val, true).
+ replace(/%26/gi, '&').
+ replace(/%3D/gi, '=').
+ replace(/%2B/gi, '+');
+}
+
+
+/**
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+ * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
+ * encoded per http://tools.ietf.org/html/rfc3986:
+ * query = *( pchar / "/" / "?" )
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriQuery(val, pctEncodeSpaces) {
+ return encodeURIComponent(val).
+ replace(/%40/gi, '@').
+ replace(/%3A/gi, ':').
+ replace(/%24/g, '$').
+ replace(/%2C/gi, ',').
+ replace(/%3B/gi, ';').
+ replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
+}
+
+var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
+
+function getNgAttribute(element, ngAttr) {
+ var attr, i, ii = ngAttrPrefixes.length;
+ element = jqLite(element);
+ for (i = 0; i < ii; ++i) {
+ attr = ngAttrPrefixes[i] + ngAttr;
+ if (isString(attr = element.attr(attr))) {
+ return attr;
+ }
+ }
+ return null;
+}
+
+/**
+ * @ngdoc directive
+ * @name ngApp
+ * @module ng
+ *
+ * @element ANY
+ * @param {angular.Module} ngApp an optional application
+ * {@link angular.module module} name to load.
+ * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
+ * created in "strict-di" mode. This means that the application will fail to invoke functions which
+ * do not use explicit function annotation (and are thus unsuitable for minification), as described
+ * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
+ * tracking down the root of these bugs.
+ *
+ * @description
+ *
+ * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
+ * designates the **root element** of the application and is typically placed near the root element
+ * of the page - e.g. on the `<body>` or `<html>` tags.
+ *
+ * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
+ * found in the document will be used to define the root element to auto-bootstrap as an
+ * application. To run multiple applications in an HTML document you must manually bootstrap them using
+ * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
+ *
+ * You can specify an **AngularJS module** to be used as the root module for the application. This
+ * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
+ * should contain the application code needed or have dependencies on other modules that will
+ * contain the code. See {@link angular.module} for more information.
+ *
+ * In the example below if the `ngApp` directive were not placed on the `html` element then the
+ * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
+ * would not be resolved to `3`.
+ *
+ * `ngApp` is the easiest, and most common way to bootstrap an application.
+ *
+ <example module="ngAppDemo">
+ <file name="index.html">
+ <div ng-controller="ngAppDemoController">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ });
+ </file>
+ </example>
+ *
+ * Using `ngStrictDi`, you would see something like this:
+ *
+ <example ng-app-included="true">
+ <file name="index.html">
+ <div ng-app="ngAppStrictDemo" ng-strict-di>
+ <div ng-controller="GoodController1">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style (see
+ script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="GoodController2">
+ Name: <input ng-model="name"><br />
+ Hello, {{name}}!
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style
+ (see script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="BadController">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>The controller could not be instantiated, due to relying
+ on automatic function annotations (which are disabled in
+ strict mode). As such, the content of this section is not
+ interpolated, and there should be an error in your web console.
+ </p>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngAppStrictDemo', [])
+ // BadController will fail to instantiate, due to relying on automatic function annotation,
+ // rather than an explicit annotation
+ .controller('BadController', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ })
+ // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
+ // due to using explicit annotations using the array style and $inject property, respectively.
+ .controller('GoodController1', ['$scope', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ }])
+ .controller('GoodController2', GoodController2);
+ function GoodController2($scope) {
+ $scope.name = "World";
+ }
+ GoodController2.$inject = ['$scope'];
+ </file>
+ <file name="style.css">
+ div[ng-controller] {
+ margin-bottom: 1em;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ border: 1px solid;
+ padding: .5em;
+ }
+ div[ng-controller^=Good] {
+ border-color: #d6e9c6;
+ background-color: #dff0d8;
+ color: #3c763d;
+ }
+ div[ng-controller^=Bad] {
+ border-color: #ebccd1;
+ background-color: #f2dede;
+ color: #a94442;
+ margin-bottom: 0;
+ }
+ </file>
+ </example>
+ */
+function angularInit(element, bootstrap) {
+ var appElement,
+ module,
+ config = {};
+
+ // The element `element` has priority over any other element
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
+
+ if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
+ appElement = element;
+ module = element.getAttribute(name);
+ }
+ });
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
+ var candidate;
+
+ if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
+ appElement = candidate;
+ module = candidate.getAttribute(name);
+ }
+ });
+ if (appElement) {
+ config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
+ bootstrap(appElement, module ? [module] : [], config);
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.bootstrap
+ * @module ng
+ * @description
+ * Use this function to manually start up angular application.
+ *
+ * See: {@link guide/bootstrap Bootstrap}
+ *
+ * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.
+ * They must use {@link ng.directive:ngApp ngApp}.
+ *
+ * Angular will detect if it has been loaded into the browser more than once and only allow the
+ * first loaded script to be bootstrapped and will report a warning to the browser console for
+ * each of the subsequent scripts. This prevents strange results in applications, where otherwise
+ * multiple instances of Angular try to work on the DOM.
+ *
+ * ```html
+ * <!doctype html>
+ * <html>
+ * <body>
+ * <div ng-controller="WelcomeController">
+ * {{greeting}}
+ * </div>
+ *
+ * <script src="angular.js"></script>
+ * <script>
+ * var app = angular.module('demo', [])
+ * .controller('WelcomeController', function($scope) {
+ * $scope.greeting = 'Welcome!';
+ * });
+ * angular.bootstrap(document, ['demo']);
+ * </script>
+ * </body>
+ * </html>
+ * ```
+ *
+ * @param {DOMElement} element DOM element which is the root of angular application.
+ * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
+ * Each item in the array should be the name of a predefined module or a (DI annotated)
+ * function that will be invoked by the injector as a `config` block.
+ * See: {@link angular.module modules}
+ * @param {Object=} config an object for defining configuration options for the application. The
+ * following keys are supported:
+ *
+ * * `strictDi` - disable automatic function annotation for the application. This is meant to
+ * assist in finding bugs which break minified code. Defaults to `false`.
+ *
+ * @returns {auto.$injector} Returns the newly created injector for this app.
+ */
+function bootstrap(element, modules, config) {
+ if (!isObject(config)) config = {};
+ var defaultConfig = {
+ strictDi: false
+ };
+ config = extend(defaultConfig, config);
+ var doBootstrap = function() {
+ element = jqLite(element);
+
+ if (element.injector()) {
+ var tag = (element[0] === document) ? 'document' : startingTag(element);
+ //Encode angle brackets to prevent input from being sanitized to empty string #8683
+ throw ngMinErr(
+ 'btstrpd',
+ "App Already Bootstrapped with this Element '{0}'",
+ tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
+ }
+
+ modules = modules || [];
+ modules.unshift(['$provide', function($provide) {
+ $provide.value('$rootElement', element);
+ }]);
+
+ if (config.debugInfoEnabled) {
+ // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.
+ modules.push(['$compileProvider', function($compileProvider) {
+ $compileProvider.debugInfoEnabled(true);
+ }]);
+ }
+
+ modules.unshift('ng');
+ var injector = createInjector(modules, config.strictDi);
+ injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
+ function bootstrapApply(scope, element, compile, injector) {
+ scope.$apply(function() {
+ element.data('$injector', injector);
+ compile(element)(scope);
+ });
+ }]
+ );
+ return injector;
+ };
+
+ var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;
+ var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
+
+ if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {
+ config.debugInfoEnabled = true;
+ window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');
+ }
+
+ if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
+ return doBootstrap();
+ }
+
+ window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
+ angular.resumeBootstrap = function(extraModules) {
+ forEach(extraModules, function(module) {
+ modules.push(module);
+ });
+ return doBootstrap();
+ };
+
+ if (isFunction(angular.resumeDeferredBootstrap)) {
+ angular.resumeDeferredBootstrap();
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.reloadWithDebugInfo
+ * @module ng
+ * @description
+ * Use this function to reload the current application with debug information turned on.
+ * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.
+ *
+ * See {@link ng.$compileProvider#debugInfoEnabled} for more.
+ */
+function reloadWithDebugInfo() {
+ window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
+ window.location.reload();
+}
+
+/**
+ * @name angular.getTestability
+ * @module ng
+ * @description
+ * Get the testability service for the instance of Angular on the given
+ * element.
+ * @param {DOMElement} element DOM element which is the root of angular application.
+ */
+function getTestability(rootElement) {
+ var injector = angular.element(rootElement).injector();
+ if (!injector) {
+ throw ngMinErr('test',
+ 'no injector found for element argument to getTestability');
+ }
+ return injector.get('$$testability');
+}
+
+var SNAKE_CASE_REGEXP = /[A-Z]/g;
+function snake_case(name, separator) {
+ separator = separator || '_';
+ return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+}
+
+var bindJQueryFired = false;
+var skipDestroyOnNextJQueryCleanData;
+function bindJQuery() {
+ var originalCleanData;
+
+ if (bindJQueryFired) {
+ return;
+ }
+
+ // bind to jQuery if present;
+ jQuery = window.jQuery;
+ // Use jQuery if it exists with proper functionality, otherwise default to us.
+ // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
+ // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
+ // versions. It will not work for sure with jQuery <1.7, though.
+ if (jQuery && jQuery.fn.on) {
+ jqLite = jQuery;
+ extend(jQuery.fn, {
+ scope: JQLitePrototype.scope,
+ isolateScope: JQLitePrototype.isolateScope,
+ controller: JQLitePrototype.controller,
+ injector: JQLitePrototype.injector,
+ inheritedData: JQLitePrototype.inheritedData
+ });
+
+ // All nodes removed from the DOM via various jQuery APIs like .remove()
+ // are passed through jQuery.cleanData. Monkey-patch this method to fire
+ // the $destroy event on all removed nodes.
+ originalCleanData = jQuery.cleanData;
+ jQuery.cleanData = function(elems) {
+ var events;
+ if (!skipDestroyOnNextJQueryCleanData) {
+ for (var i = 0, elem; (elem = elems[i]) != null; i++) {
+ events = jQuery._data(elem, "events");
+ if (events && events.$destroy) {
+ jQuery(elem).triggerHandler('$destroy');
+ }
+ }
+ } else {
+ skipDestroyOnNextJQueryCleanData = false;
+ }
+ originalCleanData(elems);
+ };
+ } else {
+ jqLite = JQLite;
+ }
+
+ angular.element = jqLite;
+
+ // Prevent double-proxying.
+ bindJQueryFired = true;
+}
+
+/**
+ * throw error if the argument is falsy.
+ */
+function assertArg(arg, name, reason) {
+ if (!arg) {
+ throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
+ }
+ return arg;
+}
+
+function assertArgFn(arg, name, acceptArrayAnnotation) {
+ if (acceptArrayAnnotation && isArray(arg)) {
+ arg = arg[arg.length - 1];
+ }
+
+ assertArg(isFunction(arg), name, 'not a function, got ' +
+ (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
+ return arg;
+}
+
+/**
+ * throw error if the name given is hasOwnProperty
+ * @param {String} name the name to test
+ * @param {String} context the context in which the name is used, such as module or directive
+ */
+function assertNotHasOwnProperty(name, context) {
+ if (name === 'hasOwnProperty') {
+ throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
+ }
+}
+
+/**
+ * Return the value accessible from the object by path. Any undefined traversals are ignored
+ * @param {Object} obj starting object
+ * @param {String} path path to traverse
+ * @param {boolean} [bindFnToScope=true]
+ * @returns {Object} value as accessible by path
+ */
+//TODO(misko): this function needs to be removed
+function getter(obj, path, bindFnToScope) {
+ if (!path) return obj;
+ var keys = path.split('.');
+ var key;
+ var lastInstance = obj;
+ var len = keys.length;
+
+ for (var i = 0; i < len; i++) {
+ key = keys[i];
+ if (obj) {
+ obj = (lastInstance = obj)[key];
+ }
+ }
+ if (!bindFnToScope && isFunction(obj)) {
+ return bind(lastInstance, obj);
+ }
+ return obj;
+}
+
+/**
+ * Return the DOM siblings between the first and last node in the given array.
+ * @param {Array} array like object
+ * @returns {jqLite} jqLite collection containing the nodes
+ */
+function getBlockNodes(nodes) {
+ // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
+ // collection, otherwise update the original collection.
+ var node = nodes[0];
+ var endNode = nodes[nodes.length - 1];
+ var blockNodes = [node];
+
+ do {
+ node = node.nextSibling;
+ if (!node) break;
+ blockNodes.push(node);
+ } while (node !== endNode);
+
+ return jqLite(blockNodes);
+}
+
+
+/**
+ * Creates a new object without a prototype. This object is useful for lookup without having to
+ * guard against prototypically inherited properties via hasOwnProperty.
+ *
+ * Related micro-benchmarks:
+ * - http://jsperf.com/object-create2
+ * - http://jsperf.com/proto-map-lookup/2
+ * - http://jsperf.com/for-in-vs-object-keys2
+ *
+ * @returns {Object}
+ */
+function createMap() {
+ return Object.create(null);
+}
+
+var NODE_TYPE_ELEMENT = 1;
+var NODE_TYPE_ATTRIBUTE = 2;
+var NODE_TYPE_TEXT = 3;
+var NODE_TYPE_COMMENT = 8;
+var NODE_TYPE_DOCUMENT = 9;
+var NODE_TYPE_DOCUMENT_FRAGMENT = 11;
+
+/**
+ * @ngdoc type
+ * @name angular.Module
+ * @module ng
+ * @description
+ *
+ * Interface for configuring angular {@link angular.module modules}.
+ */
+
+function setupModuleLoader(window) {
+
+ var $injectorMinErr = minErr('$injector');
+ var ngMinErr = minErr('ng');
+
+ function ensure(obj, name, factory) {
+ return obj[name] || (obj[name] = factory());
+ }
+
+ var angular = ensure(window, 'angular', Object);
+
+ // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
+ angular.$$minErr = angular.$$minErr || minErr;
+
+ return ensure(angular, 'module', function() {
+ /** @type {Object.<string, angular.Module>} */
+ var modules = {};
+
+ /**
+ * @ngdoc function
+ * @name angular.module
+ * @module ng
+ * @description
+ *
+ * The `angular.module` is a global place for creating, registering and retrieving Angular
+ * modules.
+ * All modules (angular core or 3rd party) that should be available to an application must be
+ * registered using this mechanism.
+ *
+ * When passed two or more arguments, a new module is created. If passed only one argument, an
+ * existing module (the name passed as the first argument to `module`) is retrieved.
+ *
+ *
+ * # Module
+ *
+ * A module is a collection of services, directives, controllers, filters, and configuration information.
+ * `angular.module` is used to configure the {@link auto.$injector $injector}.
+ *
+ * ```js
+ * // 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(['$locationProvider', function($locationProvider) {
+ * // Configure existing providers
+ * $locationProvider.hashPrefix('!');
+ * }]);
+ * ```
+ *
+ * Then you can create an injector and load your modules like this:
+ *
+ * ```js
+ * var injector = angular.injector(['ng', 'myModule'])
+ * ```
+ *
+ * However it's more likely that you'll just use
+ * {@link ng.directive:ngApp ngApp} or
+ * {@link angular.bootstrap} to simplify this process for you.
+ *
+ * @param {!string} name The name of the module to create or retrieve.
+ * @param {!Array.<string>=} requires If specified then new module is being created. If
+ * unspecified then the module is being retrieved for further configuration.
+ * @param {Function=} configFn Optional configuration function for the module. Same as
+ * {@link angular.Module#config Module#config()}.
+ * @returns {module} new module with the {@link angular.Module} api.
+ */
+ return function module(name, requires, configFn) {
+ var assertNotHasOwnProperty = function(name, context) {
+ if (name === 'hasOwnProperty') {
+ throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
+ }
+ };
+
+ assertNotHasOwnProperty(name, 'module');
+ if (requires && modules.hasOwnProperty(name)) {
+ modules[name] = null;
+ }
+ return ensure(modules, name, function() {
+ if (!requires) {
+ throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
+ "the module name or forgot to load it. If registering a module ensure that you " +
+ "specify the dependencies as the second argument.", name);
+ }
+
+ /** @type {!Array.<Array.<*>>} */
+ var invokeQueue = [];
+
+ /** @type {!Array.<Function>} */
+ var configBlocks = [];
+
+ /** @type {!Array.<Function>} */
+ var runBlocks = [];
+
+ var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
+
+ /** @type {angular.Module} */
+ var moduleInstance = {
+ // Private state
+ _invokeQueue: invokeQueue,
+ _configBlocks: configBlocks,
+ _runBlocks: runBlocks,
+
+ /**
+ * @ngdoc property
+ * @name angular.Module#requires
+ * @module ng
+ *
+ * @description
+ * Holds the list of modules which the injector will load before the current module is
+ * loaded.
+ */
+ requires: requires,
+
+ /**
+ * @ngdoc property
+ * @name angular.Module#name
+ * @module ng
+ *
+ * @description
+ * Name of the module.
+ */
+ name: name,
+
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#provider
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} providerType Construction function for creating new instance of the
+ * service.
+ * @description
+ * See {@link auto.$provide#provider $provide.provider()}.
+ */
+ provider: invokeLater('$provide', 'provider'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#factory
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} providerFunction Function for creating new instance of the service.
+ * @description
+ * See {@link auto.$provide#factory $provide.factory()}.
+ */
+ factory: invokeLater('$provide', 'factory'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#service
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} constructor A constructor function that will be instantiated.
+ * @description
+ * See {@link auto.$provide#service $provide.service()}.
+ */
+ service: invokeLater('$provide', 'service'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#value
+ * @module ng
+ * @param {string} name service name
+ * @param {*} object Service instance object.
+ * @description
+ * See {@link auto.$provide#value $provide.value()}.
+ */
+ value: invokeLater('$provide', 'value'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#constant
+ * @module ng
+ * @param {string} name constant name
+ * @param {*} object Constant value.
+ * @description
+ * Because the constant are fixed, they get applied before other provide methods.
+ * See {@link auto.$provide#constant $provide.constant()}.
+ */
+ constant: invokeLater('$provide', 'constant', 'unshift'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#animation
+ * @module ng
+ * @param {string} name animation name
+ * @param {Function} animationFactory Factory function for creating new instance of an
+ * animation.
+ * @description
+ *
+ * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
+ *
+ *
+ * Defines an animation hook that can be later used with
+ * {@link ngAnimate.$animate $animate} service and directives that use this service.
+ *
+ * ```js
+ * 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 ng.$animateProvider#register $animateProvider.register()} and
+ * {@link ngAnimate ngAnimate module} for more information.
+ */
+ animation: invokeLater('$animateProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#filter
+ * @module ng
+ * @param {string} name Filter name - this must be a valid angular expression identifier
+ * @param {Function} filterFactory Factory function for creating new instance of filter.
+ * @description
+ * See {@link ng.$filterProvider#register $filterProvider.register()}.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ */
+ filter: invokeLater('$filterProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#controller
+ * @module ng
+ * @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
+ * @module ng
+ * @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#directive $compileProvider.directive()}.
+ */
+ directive: invokeLater('$compileProvider', 'directive'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#config
+ * @module ng
+ * @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.
+ * For more about how to configure services, see
+ * {@link providers#provider-recipe Provider Recipe}.
+ */
+ config: config,
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#run
+ * @module ng
+ * @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, queue) {
+ if (!queue) queue = invokeQueue;
+ return function() {
+ queue[insertMethod || 'push']([provider, method, arguments]);
+ return moduleInstance;
+ };
+ }
+ });
+ };
+ });
+
+}
+
+/* global: toDebugString: true */
+
+function serializeObject(obj) {
+ var seen = [];
+
+ return JSON.stringify(obj, function(key, val) {
+ val = toJsonReplacer(key, val);
+ if (isObject(val)) {
+
+ if (seen.indexOf(val) >= 0) return '<<already seen>>';
+
+ seen.push(val);
+ }
+ return val;
+ });
+}
+
+function toDebugString(obj) {
+ if (typeof obj === 'function') {
+ return obj.toString().replace(/ \{[\s\S]*$/, '');
+ } else if (typeof obj === 'undefined') {
+ return 'undefined';
+ } else if (typeof obj !== 'string') {
+ return serializeObject(obj);
+ }
+ return obj;
+}
+
+/* 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,
+ ngIncludeFillContentDirective,
+ ngInitDirective,
+ ngNonBindableDirective,
+ ngPluralizeDirective,
+ ngRepeatDirective,
+ ngShowDirective,
+ ngStyleDirective,
+ ngSwitchDirective,
+ ngSwitchWhenDirective,
+ ngSwitchDefaultDirective,
+ ngOptionsDirective,
+ ngTranscludeDirective,
+ ngModelDirective,
+ ngListDirective,
+ ngChangeDirective,
+ patternDirective,
+ patternDirective,
+ requiredDirective,
+ requiredDirective,
+ minlengthDirective,
+ minlengthDirective,
+ maxlengthDirective,
+ maxlengthDirective,
+ ngValueDirective,
+ ngModelOptionsDirective,
+ ngAttributeAliasDirectives,
+ ngEventDirectives,
+
+ $AnchorScrollProvider,
+ $AnimateProvider,
+ $BrowserProvider,
+ $CacheFactoryProvider,
+ $ControllerProvider,
+ $DocumentProvider,
+ $ExceptionHandlerProvider,
+ $FilterProvider,
+ $InterpolateProvider,
+ $IntervalProvider,
+ $HttpProvider,
+ $HttpBackendProvider,
+ $LocationProvider,
+ $LogProvider,
+ $ParseProvider,
+ $RootScopeProvider,
+ $QProvider,
+ $$QProvider,
+ $$SanitizeUriProvider,
+ $SceProvider,
+ $SceDelegateProvider,
+ $SnifferProvider,
+ $TemplateCacheProvider,
+ $TemplateRequestProvider,
+ $$TestabilityProvider,
+ $TimeoutProvider,
+ $$RAFProvider,
+ $$AsyncCallbackProvider,
+ $WindowProvider,
+ $$jqLiteProvider
+*/
+
+
+/**
+ * @ngdoc object
+ * @name angular.version
+ * @module ng
+ * @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.3.20', // all of these placeholder strings will be replaced by grunt's
+ major: 1, // package task
+ minor: 3,
+ dot: 20,
+ codeName: 'shallow-translucence'
+};
+
+
+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},
+ 'getTestability': getTestability,
+ '$$minErr': minErr,
+ '$$csp': csp,
+ 'reloadWithDebugInfo': reloadWithDebugInfo
+ });
+
+ angularModule = setupModuleLoader(window);
+ try {
+ angularModule('ngLocale');
+ } catch (e) {
+ angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
+ }
+
+ angularModule('ng', ['ngLocale'], ['$provide',
+ function ngModule($provide) {
+ // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
+ $provide.provider({
+ $$sanitizeUri: $$SanitizeUriProvider
+ });
+ $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,
+ pattern: patternDirective,
+ ngPattern: patternDirective,
+ required: requiredDirective,
+ ngRequired: requiredDirective,
+ minlength: minlengthDirective,
+ ngMinlength: minlengthDirective,
+ maxlength: maxlengthDirective,
+ ngMaxlength: maxlengthDirective,
+ ngValue: ngValueDirective,
+ ngModelOptions: ngModelOptionsDirective
+ }).
+ directive({
+ ngInclude: ngIncludeFillContentDirective
+ }).
+ 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,
+ $$q: $$QProvider,
+ $sce: $SceProvider,
+ $sceDelegate: $SceDelegateProvider,
+ $sniffer: $SnifferProvider,
+ $templateCache: $TemplateCacheProvider,
+ $templateRequest: $TemplateRequestProvider,
+ $$testability: $$TestabilityProvider,
+ $timeout: $TimeoutProvider,
+ $window: $WindowProvider,
+ $$rAF: $$RAFProvider,
+ $$asyncCallback: $$AsyncCallbackProvider,
+ $$jqLite: $$jqLiteProvider
+ });
+ }
+ ]);
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* global JQLitePrototype: true,
+ addEventListenerFn: true,
+ removeEventListenerFn: true,
+ BOOLEAN_ATTR: true,
+ ALIASED_ATTR: true,
+*/
+
+//////////////////////////////////
+//JQLite
+//////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.element
+ * @module ng
+ * @kind 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."
+ *
+ * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
+ * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
+ * commonly needed functionality with the goal of having a very small footprint.</div>
+ *
+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
+ *
+ * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
+ * jqLite; they are never raw DOM references.</div>
+ *
+ * ## Angular's jqLite
+ * jqLite provides only the following jQuery methods:
+ *
+ * - [`addClass()`](http://api.jquery.com/addClass/)
+ * - [`after()`](http://api.jquery.com/after/)
+ * - [`append()`](http://api.jquery.com/append/)
+ * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
+ * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
+ * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
+ * - [`clone()`](http://api.jquery.com/clone/)
+ * - [`contents()`](http://api.jquery.com/contents/)
+ * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
+ * - [`data()`](http://api.jquery.com/data/)
+ * - [`detach()`](http://api.jquery.com/detach/)
+ * - [`empty()`](http://api.jquery.com/empty/)
+ * - [`eq()`](http://api.jquery.com/eq/)
+ * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
+ * - [`hasClass()`](http://api.jquery.com/hasClass/)
+ * - [`html()`](http://api.jquery.com/html/)
+ * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
+ * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
+ * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
+ * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
+ * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
+ * - [`prepend()`](http://api.jquery.com/prepend/)
+ * - [`prop()`](http://api.jquery.com/prop/)
+ * - [`ready()`](http://api.jquery.com/ready/)
+ * - [`remove()`](http://api.jquery.com/remove/)
+ * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
+ * - [`removeClass()`](http://api.jquery.com/removeClass/)
+ * - [`removeData()`](http://api.jquery.com/removeData/)
+ * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
+ * - [`text()`](http://api.jquery.com/text/)
+ * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
+ * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
+ * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
+ * - [`val()`](http://api.jquery.com/val/)
+ * - [`wrap()`](http://api.jquery.com/wrap/)
+ *
+ * ## jQuery/jqLite Extras
+ * Angular also provides the following additional methods and events to both jQuery and jqLite:
+ *
+ * ### Events
+ * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
+ * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
+ * element before it is removed.
+ *
+ * ### Methods
+ * - `controller(name)` - retrieves the controller of the current element or its parent. By default
+ * retrieves controller associated with the `ngController` directive. If `name` is provided as
+ * camelCase directive name, then the controller for this directive will be retrieved (e.g.
+ * `'ngModel'`).
+ * - `injector()` - retrieves the injector of the current element or its parent.
+ * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
+ * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
+ * be enabled.
+ * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
+ * current element. This getter should be used only on elements that contain a directive which starts a new isolate
+ * scope. Calling `scope()` on this element always returns the original non-isolate scope.
+ * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
+ * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
+ * parent element is reached.
+ *
+ * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
+ * @returns {Object} jQuery object.
+ */
+
+JQLite.expando = 'ng339';
+
+var jqCache = JQLite.cache = {},
+ jqId = 1,
+ addEventListenerFn = function(element, type, fn) {
+ element.addEventListener(type, fn, false);
+ },
+ removeEventListenerFn = function(element, type, fn) {
+ element.removeEventListener(type, fn, false);
+ };
+
+/*
+ * !!! This is an undocumented "private" function !!!
+ */
+JQLite._data = function(node) {
+ //jQuery always returns an object on cache miss
+ return this.cache[node[this.expando]] || {};
+};
+
+function jqNextId() { return ++jqId; }
+
+
+var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
+var MOZ_HACK_REGEXP = /^moz([A-Z])/;
+var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
+var jqLiteMinErr = minErr('jqLite');
+
+/**
+ * Converts snake_case to camelCase.
+ * Also there is special case for Moz prefix starting with upper case letter.
+ * @param name Name to normalize
+ */
+function camelCase(name) {
+ return name.
+ replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
+ return offset ? letter.toUpperCase() : letter;
+ }).
+ replace(MOZ_HACK_REGEXP, 'Moz$1');
+}
+
+var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
+var HTML_REGEXP = /<|&#?\w+;/;
+var TAG_NAME_REGEXP = /<([\w:]+)/;
+var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
+
+var wrapMap = {
+ 'option': [1, '<select multiple="multiple">', '</select>'],
+
+ 'thead': [1, '<table>', '</table>'],
+ 'col': [2, '<table><colgroup>', '</colgroup></table>'],
+ 'tr': [2, '<table><tbody>', '</tbody></table>'],
+ 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
+ '_default': [0, "", ""]
+};
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function jqLiteIsTextNode(html) {
+ return !HTML_REGEXP.test(html);
+}
+
+function jqLiteAcceptsData(node) {
+ // The window object can accept data but has no nodeType
+ // Otherwise we are only interested in elements (1) and documents (9)
+ var nodeType = node.nodeType;
+ return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
+}
+
+function jqLiteBuildFragment(html, context) {
+ var tmp, tag, wrap,
+ fragment = context.createDocumentFragment(),
+ nodes = [], i;
+
+ if (jqLiteIsTextNode(html)) {
+ // Convert non-html into a text node
+ nodes.push(context.createTextNode(html));
+ } else {
+ // Convert html into DOM nodes
+ tmp = tmp || fragment.appendChild(context.createElement("div"));
+ tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
+ wrap = wrapMap[tag] || wrapMap._default;
+ tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
+
+ // Descend through wrappers to the right content
+ i = wrap[0];
+ while (i--) {
+ tmp = tmp.lastChild;
+ }
+
+ nodes = concat(nodes, tmp.childNodes);
+
+ tmp = fragment.firstChild;
+ tmp.textContent = "";
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+ fragment.innerHTML = ""; // Clear inner HTML
+ forEach(nodes, function(node) {
+ fragment.appendChild(node);
+ });
+
+ return fragment;
+}
+
+function jqLiteParseHTML(html, context) {
+ context = context || document;
+ var parsed;
+
+ if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
+ return [context.createElement(parsed[1])];
+ }
+
+ if ((parsed = jqLiteBuildFragment(html, context))) {
+ return parsed.childNodes;
+ }
+
+ return [];
+}
+
+/////////////////////////////////////////////
+function JQLite(element) {
+ if (element instanceof JQLite) {
+ return element;
+ }
+
+ var argIsString;
+
+ if (isString(element)) {
+ element = trim(element);
+ argIsString = true;
+ }
+ if (!(this instanceof JQLite)) {
+ if (argIsString && element.charAt(0) != '<') {
+ throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
+ }
+ return new JQLite(element);
+ }
+
+ if (argIsString) {
+ jqLiteAddNodes(this, jqLiteParseHTML(element));
+ } else {
+ jqLiteAddNodes(this, element);
+ }
+}
+
+function jqLiteClone(element) {
+ return element.cloneNode(true);
+}
+
+function jqLiteDealoc(element, onlyDescendants) {
+ if (!onlyDescendants) jqLiteRemoveData(element);
+
+ if (element.querySelectorAll) {
+ var descendants = element.querySelectorAll('*');
+ for (var i = 0, l = descendants.length; i < l; i++) {
+ jqLiteRemoveData(descendants[i]);
+ }
+ }
+}
+
+function jqLiteOff(element, type, fn, unsupported) {
+ if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
+
+ var expandoStore = jqLiteExpandoStore(element);
+ var events = expandoStore && expandoStore.events;
+ var handle = expandoStore && expandoStore.handle;
+
+ if (!handle) return; //no listeners registered
+
+ if (!type) {
+ for (type in events) {
+ if (type !== '$destroy') {
+ removeEventListenerFn(element, type, handle);
+ }
+ delete events[type];
+ }
+ } else {
+ forEach(type.split(' '), function(type) {
+ if (isDefined(fn)) {
+ var listenerFns = events[type];
+ arrayRemove(listenerFns || [], fn);
+ if (listenerFns && listenerFns.length > 0) {
+ return;
+ }
+ }
+
+ removeEventListenerFn(element, type, handle);
+ delete events[type];
+ });
+ }
+}
+
+function jqLiteRemoveData(element, name) {
+ var expandoId = element.ng339;
+ var expandoStore = expandoId && jqCache[expandoId];
+
+ if (expandoStore) {
+ if (name) {
+ delete expandoStore.data[name];
+ return;
+ }
+
+ if (expandoStore.handle) {
+ if (expandoStore.events.$destroy) {
+ expandoStore.handle({}, '$destroy');
+ }
+ jqLiteOff(element);
+ }
+ delete jqCache[expandoId];
+ element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
+ }
+}
+
+
+function jqLiteExpandoStore(element, createIfNecessary) {
+ var expandoId = element.ng339,
+ expandoStore = expandoId && jqCache[expandoId];
+
+ if (createIfNecessary && !expandoStore) {
+ element.ng339 = expandoId = jqNextId();
+ expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};
+ }
+
+ return expandoStore;
+}
+
+
+function jqLiteData(element, key, value) {
+ if (jqLiteAcceptsData(element)) {
+
+ var isSimpleSetter = isDefined(value);
+ var isSimpleGetter = !isSimpleSetter && key && !isObject(key);
+ var massGetter = !key;
+ var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);
+ var data = expandoStore && expandoStore.data;
+
+ if (isSimpleSetter) { // data('key', value)
+ data[key] = value;
+ } else {
+ if (massGetter) { // data()
+ return data;
+ } else {
+ if (isSimpleGetter) { // data('key')
+ // don't force creation of expandoStore if it doesn't exist yet
+ return data && data[key];
+ } else { // mass-setter: data({key1: val1, key2: val2})
+ extend(data, key);
+ }
+ }
+ }
+ }
+}
+
+function jqLiteHasClass(element, selector) {
+ if (!element.getAttribute) return false;
+ return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
+ indexOf(" " + selector + " ") > -1);
+}
+
+function jqLiteRemoveClass(element, cssClasses) {
+ if (cssClasses && element.setAttribute) {
+ forEach(cssClasses.split(' '), function(cssClass) {
+ element.setAttribute('class', trim(
+ (" " + (element.getAttribute('class') || '') + " ")
+ .replace(/[\n\t]/g, " ")
+ .replace(" " + trim(cssClass) + " ", " "))
+ );
+ });
+ }
+}
+
+function jqLiteAddClass(element, cssClasses) {
+ if (cssClasses && element.setAttribute) {
+ var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
+ .replace(/[\n\t]/g, " ");
+
+ forEach(cssClasses.split(' '), function(cssClass) {
+ cssClass = trim(cssClass);
+ if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
+ existingClasses += cssClass + ' ';
+ }
+ });
+
+ element.setAttribute('class', trim(existingClasses));
+ }
+}
+
+
+function jqLiteAddNodes(root, elements) {
+ // THIS CODE IS VERY HOT. Don't make changes without benchmarking.
+
+ if (elements) {
+
+ // if a Node (the most common case)
+ if (elements.nodeType) {
+ root[root.length++] = elements;
+ } else {
+ var length = elements.length;
+
+ // if an Array or NodeList and not a Window
+ if (typeof length === 'number' && elements.window !== elements) {
+ if (length) {
+ for (var i = 0; i < length; i++) {
+ root[root.length++] = elements[i];
+ }
+ }
+ } else {
+ root[root.length++] = elements;
+ }
+ }
+ }
+}
+
+
+function jqLiteController(element, name) {
+ return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
+}
+
+function jqLiteInheritedData(element, name, value) {
+ // if element is the document object work with the html element instead
+ // this makes $(document).scope() possible
+ if (element.nodeType == NODE_TYPE_DOCUMENT) {
+ element = element.documentElement;
+ }
+ var names = isArray(name) ? name : [name];
+
+ while (element) {
+ for (var i = 0, ii = names.length; i < ii; i++) {
+ if ((value = jqLite.data(element, names[i])) !== undefined) return value;
+ }
+
+ // If dealing with a document fragment node with a host element, and no parent, use the host
+ // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
+ // to lookup parent controllers.
+ element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);
+ }
+}
+
+function jqLiteEmpty(element) {
+ jqLiteDealoc(element, true);
+ while (element.firstChild) {
+ element.removeChild(element.firstChild);
+ }
+}
+
+function jqLiteRemove(element, keepData) {
+ if (!keepData) jqLiteDealoc(element);
+ var parent = element.parentNode;
+ if (parent) parent.removeChild(element);
+}
+
+
+function jqLiteDocumentLoaded(action, win) {
+ win = win || window;
+ if (win.document.readyState === 'complete') {
+ // Force the action to be run async for consistent behaviour
+ // from the action's point of view
+ // i.e. it will definitely not be in a $apply
+ win.setTimeout(action);
+ } else {
+ // No need to unbind this handler as load is only ever called once
+ jqLite(win).on('load', action);
+ }
+}
+
+//////////////////////////////////////////
+// Functions which are declared directly.
+//////////////////////////////////////////
+var JQLitePrototype = JQLite.prototype = {
+ ready: function(fn) {
+ var fired = false;
+
+ function trigger() {
+ if (fired) return;
+ fired = true;
+ fn();
+ }
+
+ // check if document is already loaded
+ if (document.readyState === 'complete') {
+ setTimeout(trigger);
+ } else {
+ this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
+ // we can not use jqLite since we are not done loading and jQuery could be loaded later.
+ // jshint -W064
+ JQLite(window).on('load', trigger); // fallback to window.onload for others
+ // jshint +W064
+ }
+ },
+ toString: function() {
+ var value = [];
+ forEach(this, function(e) { value.push('' + e);});
+ return '[' + value.join(', ') + ']';
+ },
+
+ eq: function(index) {
+ return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
+ },
+
+ length: 0,
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+//////////////////////////////////////////
+// Functions iterating getter/setters.
+// these functions return self on setter and
+// value on get.
+//////////////////////////////////////////
+var BOOLEAN_ATTR = {};
+forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
+ BOOLEAN_ATTR[lowercase(value)] = value;
+});
+var BOOLEAN_ELEMENTS = {};
+forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
+ BOOLEAN_ELEMENTS[value] = true;
+});
+var ALIASED_ATTR = {
+ 'ngMinlength': 'minlength',
+ 'ngMaxlength': 'maxlength',
+ 'ngMin': 'min',
+ 'ngMax': 'max',
+ 'ngPattern': 'pattern'
+};
+
+function getBooleanAttrName(element, name) {
+ // check dom last since we will most likely fail on name
+ var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
+
+ // booleanAttr is here twice to minimize DOM access
+ return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
+}
+
+function getAliasedAttrName(element, name) {
+ var nodeName = element.nodeName;
+ return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
+}
+
+forEach({
+ data: jqLiteData,
+ removeData: jqLiteRemoveData
+}, function(fn, name) {
+ JQLite[name] = fn;
+});
+
+forEach({
+ data: jqLiteData,
+ inheritedData: jqLiteInheritedData,
+
+ scope: function(element) {
+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
+ return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
+ },
+
+ isolateScope: function(element) {
+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
+ return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
+ },
+
+ controller: jqLiteController,
+
+ injector: function(element) {
+ return jqLiteInheritedData(element, '$injector');
+ },
+
+ removeAttr: function(element, name) {
+ element.removeAttribute(name);
+ },
+
+ hasClass: jqLiteHasClass,
+
+ css: function(element, name, value) {
+ name = camelCase(name);
+
+ if (isDefined(value)) {
+ element.style[name] = value;
+ } else {
+ return element.style[name];
+ }
+ },
+
+ attr: function(element, name, value) {
+ var nodeType = element.nodeType;
+ if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
+ return;
+ }
+ var lowercasedName = lowercase(name);
+ if (BOOLEAN_ATTR[lowercasedName]) {
+ if (isDefined(value)) {
+ if (!!value) {
+ element[name] = true;
+ element.setAttribute(name, lowercasedName);
+ } else {
+ element[name] = false;
+ element.removeAttribute(lowercasedName);
+ }
+ } else {
+ return (element[name] ||
+ (element.attributes.getNamedItem(name) || noop).specified)
+ ? lowercasedName
+ : undefined;
+ }
+ } else if (isDefined(value)) {
+ element.setAttribute(name, value);
+ } else if (element.getAttribute) {
+ // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
+ // some elements (e.g. Document) don't have get attribute, so return undefined
+ var ret = element.getAttribute(name, 2);
+ // normalize non-existing attributes to undefined (as jQuery)
+ return ret === null ? undefined : ret;
+ }
+ },
+
+ prop: function(element, name, value) {
+ if (isDefined(value)) {
+ element[name] = value;
+ } else {
+ return element[name];
+ }
+ },
+
+ text: (function() {
+ getText.$dv = '';
+ return getText;
+
+ function getText(element, value) {
+ if (isUndefined(value)) {
+ var nodeType = element.nodeType;
+ return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';
+ }
+ element.textContent = value;
+ }
+ })(),
+
+ val: function(element, value) {
+ if (isUndefined(value)) {
+ if (element.multiple && nodeName_(element) === 'select') {
+ var result = [];
+ forEach(element.options, function(option) {
+ if (option.selected) {
+ result.push(option.value || option.text);
+ }
+ });
+ return result.length === 0 ? null : result;
+ }
+ return element.value;
+ }
+ element.value = value;
+ },
+
+ html: function(element, value) {
+ if (isUndefined(value)) {
+ return element.innerHTML;
+ }
+ jqLiteDealoc(element, true);
+ element.innerHTML = value;
+ },
+
+ empty: jqLiteEmpty
+}, function(fn, name) {
+ /**
+ * Properties: writes return selection, reads return first value
+ */
+ JQLite.prototype[name] = function(arg1, arg2) {
+ var i, key;
+ var nodeCount = this.length;
+
+ // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
+ // in a way that survives minification.
+ // jqLiteEmpty takes no arguments but is a setter.
+ if (fn !== jqLiteEmpty &&
+ (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
+ if (isObject(arg1)) {
+
+ // we are a write, but the object properties are the key/values
+ for (i = 0; i < nodeCount; i++) {
+ if (fn === jqLiteData) {
+ // data() takes the whole object in jQuery
+ fn(this[i], arg1);
+ } else {
+ for (key in arg1) {
+ fn(this[i], key, arg1[key]);
+ }
+ }
+ }
+ // return self for chaining
+ return this;
+ } else {
+ // we are a read, so read the first child.
+ // TODO: do we still need this?
+ var value = fn.$dv;
+ // Only if we have $dv do we iterate over all, otherwise it is just the first element.
+ var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
+ for (var j = 0; j < jj; j++) {
+ var nodeValue = fn(this[j], arg1, arg2);
+ value = value ? value + nodeValue : nodeValue;
+ }
+ return value;
+ }
+ } else {
+ // we are a write, so apply to all children
+ for (i = 0; i < nodeCount; i++) {
+ fn(this[i], arg1, arg2);
+ }
+ // return self for chaining
+ return this;
+ }
+ };
+});
+
+function createEventHandler(element, events) {
+ var eventHandler = function(event, type) {
+ // jQuery specific api
+ event.isDefaultPrevented = function() {
+ return event.defaultPrevented;
+ };
+
+ var eventFns = events[type || event.type];
+ var eventFnsLength = eventFns ? eventFns.length : 0;
+
+ if (!eventFnsLength) return;
+
+ if (isUndefined(event.immediatePropagationStopped)) {
+ var originalStopImmediatePropagation = event.stopImmediatePropagation;
+ event.stopImmediatePropagation = function() {
+ event.immediatePropagationStopped = true;
+
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ }
+
+ if (originalStopImmediatePropagation) {
+ originalStopImmediatePropagation.call(event);
+ }
+ };
+ }
+
+ event.isImmediatePropagationStopped = function() {
+ return event.immediatePropagationStopped === true;
+ };
+
+ // Copy event handlers in case event handlers array is modified during execution.
+ if ((eventFnsLength > 1)) {
+ eventFns = shallowCopy(eventFns);
+ }
+
+ for (var i = 0; i < eventFnsLength; i++) {
+ if (!event.isImmediatePropagationStopped()) {
+ eventFns[i].call(element, event);
+ }
+ }
+ };
+
+ // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
+ // events on `element`
+ eventHandler.elem = element;
+ return eventHandler;
+}
+
+//////////////////////////////////////////
+// Functions iterating traversal.
+// These functions chain results into a single
+// selector.
+//////////////////////////////////////////
+forEach({
+ removeData: jqLiteRemoveData,
+
+ on: function jqLiteOn(element, type, fn, unsupported) {
+ if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
+
+ // Do not add event handlers to non-elements because they will not be cleaned up.
+ if (!jqLiteAcceptsData(element)) {
+ return;
+ }
+
+ var expandoStore = jqLiteExpandoStore(element, true);
+ var events = expandoStore.events;
+ var handle = expandoStore.handle;
+
+ if (!handle) {
+ handle = expandoStore.handle = createEventHandler(element, events);
+ }
+
+ // http://jsperf.com/string-indexof-vs-split
+ var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
+ var i = types.length;
+
+ while (i--) {
+ type = types[i];
+ var eventFns = events[type];
+
+ if (!eventFns) {
+ events[type] = [];
+
+ if (type === 'mouseenter' || type === 'mouseleave') {
+ // Refer to jQuery's implementation of mouseenter & mouseleave
+ // Read about mouseenter and mouseleave:
+ // http://www.quirksmode.org/js/events_mouse.html#link8
+
+ jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
+ var target = this, related = event.relatedTarget;
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if (!related || (related !== target && !target.contains(related))) {
+ handle(event, type);
+ }
+ });
+
+ } else {
+ if (type !== '$destroy') {
+ addEventListenerFn(element, type, handle);
+ }
+ }
+ eventFns = events[type];
+ }
+ eventFns.push(fn);
+ }
+ },
+
+ off: jqLiteOff,
+
+ one: function(element, type, fn) {
+ element = jqLite(element);
+
+ //add the listener twice so that when it is called
+ //you can remove the original function and still be
+ //able to call element.off(ev, fn) normally
+ element.on(type, function onFn() {
+ element.off(type, fn);
+ element.off(type, onFn);
+ });
+ element.on(type, fn);
+ },
+
+ replaceWith: function(element, replaceNode) {
+ var index, parent = element.parentNode;
+ jqLiteDealoc(element);
+ forEach(new JQLite(replaceNode), function(node) {
+ if (index) {
+ parent.insertBefore(node, index.nextSibling);
+ } else {
+ parent.replaceChild(node, element);
+ }
+ index = node;
+ });
+ },
+
+ children: function(element) {
+ var children = [];
+ forEach(element.childNodes, function(element) {
+ if (element.nodeType === NODE_TYPE_ELEMENT)
+ children.push(element);
+ });
+ return children;
+ },
+
+ contents: function(element) {
+ return element.contentDocument || element.childNodes || [];
+ },
+
+ append: function(element, node) {
+ var nodeType = element.nodeType;
+ if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
+
+ node = new JQLite(node);
+
+ for (var i = 0, ii = node.length; i < ii; i++) {
+ var child = node[i];
+ element.appendChild(child);
+ }
+ },
+
+ prepend: function(element, node) {
+ if (element.nodeType === NODE_TYPE_ELEMENT) {
+ var index = element.firstChild;
+ forEach(new JQLite(node), function(child) {
+ element.insertBefore(child, index);
+ });
+ }
+ },
+
+ wrap: function(element, wrapNode) {
+ wrapNode = jqLite(wrapNode).eq(0).clone()[0];
+ var parent = element.parentNode;
+ if (parent) {
+ parent.replaceChild(wrapNode, element);
+ }
+ wrapNode.appendChild(element);
+ },
+
+ remove: jqLiteRemove,
+
+ detach: function(element) {
+ jqLiteRemove(element, true);
+ },
+
+ after: function(element, newElement) {
+ var index = element, parent = element.parentNode;
+ newElement = new JQLite(newElement);
+
+ for (var i = 0, ii = newElement.length; i < ii; i++) {
+ var node = newElement[i];
+ parent.insertBefore(node, index.nextSibling);
+ index = node;
+ }
+ },
+
+ addClass: jqLiteAddClass,
+ removeClass: jqLiteRemoveClass,
+
+ toggleClass: function(element, selector, condition) {
+ if (selector) {
+ forEach(selector.split(' '), function(className) {
+ var classCondition = condition;
+ if (isUndefined(classCondition)) {
+ classCondition = !jqLiteHasClass(element, className);
+ }
+ (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
+ });
+ }
+ },
+
+ parent: function(element) {
+ var parent = element.parentNode;
+ return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;
+ },
+
+ next: function(element) {
+ return element.nextElementSibling;
+ },
+
+ find: function(element, selector) {
+ if (element.getElementsByTagName) {
+ return element.getElementsByTagName(selector);
+ } else {
+ return [];
+ }
+ },
+
+ clone: jqLiteClone,
+
+ triggerHandler: function(element, event, extraParameters) {
+
+ var dummyEvent, eventFnsCopy, handlerArgs;
+ var eventName = event.type || event;
+ var expandoStore = jqLiteExpandoStore(element);
+ var events = expandoStore && expandoStore.events;
+ var eventFns = events && events[eventName];
+
+ if (eventFns) {
+ // Create a dummy event to pass to the handlers
+ dummyEvent = {
+ preventDefault: function() { this.defaultPrevented = true; },
+ isDefaultPrevented: function() { return this.defaultPrevented === true; },
+ stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
+ isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
+ stopPropagation: noop,
+ type: eventName,
+ target: element
+ };
+
+ // If a custom event was provided then extend our dummy event with it
+ if (event.type) {
+ dummyEvent = extend(dummyEvent, event);
+ }
+
+ // Copy event handlers in case event handlers array is modified during execution.
+ eventFnsCopy = shallowCopy(eventFns);
+ handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
+
+ forEach(eventFnsCopy, function(fn) {
+ if (!dummyEvent.isImmediatePropagationStopped()) {
+ fn.apply(element, handlerArgs);
+ }
+ });
+ }
+ }
+}, function(fn, name) {
+ /**
+ * chaining functions
+ */
+ JQLite.prototype[name] = function(arg1, arg2, arg3) {
+ var value;
+
+ for (var i = 0, ii = this.length; i < ii; i++) {
+ if (isUndefined(value)) {
+ value = fn(this[i], arg1, arg2, arg3);
+ if (isDefined(value)) {
+ // any function which returns a value needs to be wrapped
+ value = jqLite(value);
+ }
+ } else {
+ jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
+ }
+ }
+ return isDefined(value) ? value : this;
+ };
+
+ // bind legacy bind/unbind to on/off
+ JQLite.prototype.bind = JQLite.prototype.on;
+ JQLite.prototype.unbind = JQLite.prototype.off;
+});
+
+
+// Provider for private $$jqLite service
+function $$jqLiteProvider() {
+ this.$get = function $$jqLite() {
+ return extend(JQLite, {
+ hasClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteHasClass(node, classes);
+ },
+ addClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteAddClass(node, classes);
+ },
+ removeClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteRemoveClass(node, classes);
+ }
+ });
+ };
+}
+
+/**
+ * Computes a hash of an 'obj'.
+ * Hash of a:
+ * string is string
+ * number is number as string
+ * object is either result of calling $$hashKey function on the object or uniquely generated id,
+ * that is also assigned to the $$hashKey property of the object.
+ *
+ * @param obj
+ * @returns {string} hash string such that the same input will have the same hash string.
+ * The resulting string key is in 'type:hashKey' format.
+ */
+function hashKey(obj, nextUidFn) {
+ var key = obj && obj.$$hashKey;
+
+ if (key) {
+ if (typeof key === 'function') {
+ key = obj.$$hashKey();
+ }
+ return key;
+ }
+
+ var objType = typeof obj;
+ if (objType == 'function' || (objType == 'object' && obj !== null)) {
+ key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();
+ } else {
+ key = objType + ':' + obj;
+ }
+
+ return key;
+}
+
+/**
+ * HashMap which can use objects as keys
+ */
+function HashMap(array, isolatedUid) {
+ if (isolatedUid) {
+ var uid = 0;
+ this.nextUid = function() {
+ return ++uid;
+ };
+ }
+ forEach(array, this.put, this);
+}
+HashMap.prototype = {
+ /**
+ * Store key value pair
+ * @param key key to store can be any type
+ * @param value value to store can be any type
+ */
+ put: function(key, value) {
+ this[hashKey(key, this.nextUid)] = value;
+ },
+
+ /**
+ * @param key
+ * @returns {Object} the value for the key
+ */
+ get: function(key) {
+ return this[hashKey(key, this.nextUid)];
+ },
+
+ /**
+ * Remove the key/value pair
+ * @param key
+ */
+ remove: function(key) {
+ var value = this[key = hashKey(key, this.nextUid)];
+ delete this[key];
+ return value;
+ }
+};
+
+/**
+ * @ngdoc function
+ * @module ng
+ * @name angular.injector
+ * @kind function
+ *
+ * @description
+ * Creates an injector object that can be used for retrieving services as well as for
+ * dependency injection (see {@link guide/di dependency injection}).
+ *
+ * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
+ * {@link angular.module}. The `ng` module must be explicitly added.
+ * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
+ * disallows argument name annotation inference.
+ * @returns {injector} Injector object. See {@link auto.$injector $injector}.
+ *
+ * @example
+ * Typical usage
+ * ```js
+ * // 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();
+ * });
+ * ```
+ *
+ * Sometimes you want to get access to the injector of a currently running Angular app
+ * from outside Angular. Perhaps, you want to inject and compile some markup after the
+ * application has been bootstrapped. You can do this using the extra `injector()` added
+ * to JQuery/jqLite elements. See {@link angular.element}.
+ *
+ * *This is fairly rare but could be the case if a third party library is injecting the
+ * markup.*
+ *
+ * In the following example a new block of HTML containing a `ng-controller`
+ * directive is added to the end of the document body by JQuery. We then compile and link
+ * it into the current AngularJS scope.
+ *
+ * ```js
+ * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
+ * $(document.body).append($div);
+ *
+ * angular.element(document).injector().invoke(function($compile) {
+ * var scope = angular.element($div).scope();
+ * $compile($div)(scope);
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc module
+ * @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 anonFn(fn) {
+ // For anonymous functions, showing at the very least the function signature can help in
+ // debugging.
+ var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
+ args = fnText.match(FN_ARGS);
+ if (args) {
+ return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
+ }
+ return 'fn';
+}
+
+function annotate(fn, strictDi, name) {
+ var $inject,
+ fnText,
+ argDecl,
+ last;
+
+ if (typeof fn === 'function') {
+ if (!($inject = fn.$inject)) {
+ $inject = [];
+ if (fn.length) {
+ if (strictDi) {
+ if (!isString(name) || !name) {
+ name = fn.name || anonFn(fn);
+ }
+ throw $injectorMinErr('strictdi',
+ '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
+ }
+ 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 service
+ * @name $injector
+ *
+ * @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:
+ *
+ * ```js
+ * 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.
+ *
+ * ```js
+ * // 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. This method of discovering
+ * annotations is disallowed when the injector is in strict mode.
+ * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
+ * argument names.
+ *
+ * ## `$inject` Annotation
+ * By adding an `$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 $injector#get
+ *
+ * @description
+ * Return an instance of the service.
+ *
+ * @param {string} name The name of the instance to retrieve.
+ * @param {string=} caller An optional string to provide the origin of the function call for error messages.
+ * @return {*} The instance.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#invoke
+ *
+ * @description
+ * Invoke the method and supply the method arguments from the `$injector`.
+ *
+ * @param {Function|Array.<string|Function>} fn The injectable 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 $injector#has
+ *
+ * @description
+ * Allows the user to query if the particular service exists.
+ *
+ * @param {string} name Name of the service to query.
+ * @returns {boolean} `true` if injector has given service.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#instantiate
+ * @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 $injector#annotate
+ *
+ * @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.
+ * ```js
+ * // Given
+ * function MyController($scope, $route) {
+ * // ...
+ * }
+ *
+ * // Then
+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * ```
+ *
+ * You can disallow this method by using strict injection mode.
+ *
+ * This method does not work with code minification / obfuscation. For this reason the following
+ * annotation strategies are supported.
+ *
+ * # 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.
+ * ```js
+ * // 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:
+ *
+ * ```js
+ * // 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.<string|Function>} fn Function for which dependent service names need to
+ * be retrieved as described above.
+ *
+ * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
+ *
+ * @returns {Array.<string>} The names of the services which the function requires.
+ */
+
+
+
+
+/**
+ * @ngdoc service
+ * @name $provide
+ *
+ * @description
+ *
+ * The {@link auto.$provide $provide} service has a number of methods for registering components
+ * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
+ * {@link angular.Module}.
+ *
+ * An Angular **service** is a singleton object created by a **service factory**. These **service
+ * factories** are functions which, in turn, are created by a **service provider**.
+ * The **service providers** are constructor functions. When instantiated they must contain a
+ * property called `$get`, which holds the **service factory** function.
+ *
+ * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
+ * correct **service provider**, instantiating it and then calling its `$get` **service factory**
+ * function to get the instance of the **service**.
+ *
+ * Often services have no configuration options and there is no need to add methods to the service
+ * provider. The provider will be no more than a constructor function with a `$get` property. For
+ * these cases the {@link auto.$provide $provide} service has additional helper methods to register
+ * services without specifying a provider.
+ *
+ * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
+ * {@link auto.$injector $injector}
+ * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
+ * providers and services.
+ * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
+ * services, not providers.
+ * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
+ * that will be wrapped in a **service provider** object, whose `$get` property will contain the
+ * given factory function.
+ * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
+ * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
+ * a new object using the given constructor function.
+ *
+ * See the individual methods for more information and examples.
+ */
+
+/**
+ * @ngdoc method
+ * @name $provide#provider
+ * @description
+ *
+ * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
+ * are constructor functions, whose instances are responsible for "providing" a factory for a
+ * service.
+ *
+ * Service provider names start with the name of the service they provide followed by `Provider`.
+ * For example, the {@link ng.$log $log} service has a provider called
+ * {@link ng.$logProvider $logProvider}.
+ *
+ * Service provider objects can have additional methods which allow configuration of the provider
+ * and its service. Importantly, you can configure what kind of service is created by the `$get`
+ * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
+ * method {@link ng.$logProvider#debugEnabled debugEnabled}
+ * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
+ * console or not.
+ *
+ * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
+ 'Provider'` key.
+ * @param {(Object|function())} provider If the provider is:
+ *
+ * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
+ * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
+ * - `Constructor`: a new instance of the provider will be created using
+ * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
+ *
+ * @returns {Object} registered provider instance
+
+ * @example
+ *
+ * The following example shows how to create a simple event tracking service and register it using
+ * {@link auto.$provide#provider $provide.provider()}.
+ *
+ * ```js
+ * // 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 $provide#factory
+ * @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|Array.<string|Function>} $getFn The injectable $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
+ * ```js
+ * $provide.factory('ping', ['$http', function($http) {
+ * return function ping() {
+ * return $http.send('/ping');
+ * };
+ * }]);
+ * ```
+ * You would then inject and use this service like this:
+ * ```js
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping();
+ * }]);
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#service
+ * @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#service $provide.service(class)} if you define your service
+ * as a type/class.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function|Array.<string|Function>} constructor An injectable 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#service $provide.service(class)}.
+ * ```js
+ * var Ping = function($http) {
+ * this.$http = $http;
+ * };
+ *
+ * Ping.$inject = ['$http'];
+ *
+ * Ping.prototype.send = function() {
+ * return this.$http.get('/ping');
+ * };
+ * $provide.service('ping', Ping);
+ * ```
+ * You would then inject and use this service like this:
+ * ```js
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping.send();
+ * }]);
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#value
+ * @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.
+ * ```js
+ * $provide.value('ADMIN_USER', 'admin');
+ *
+ * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
+ *
+ * $provide.value('halfOf', function(value) {
+ * return value / 2;
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#constant
+ * @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:
+ * ```js
+ * $provide.constant('SHARD_HEIGHT', 306);
+ *
+ * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
+ *
+ * $provide.constant('double', function(value) {
+ * return value * 2;
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#decorator
+ * @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|Array.<string|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()}.
+ * ```js
+ * $provide.decorator('$log', ['$delegate', function($delegate) {
+ * $delegate.warn = $delegate.error;
+ * return $delegate;
+ * }]);
+ * ```
+ */
+
+
+function createInjector(modulesToLoad, strictDi) {
+ strictDi = (strictDi === true);
+ var INSTANTIATING = {},
+ providerSuffix = 'Provider',
+ path = [],
+ loadedModules = new HashMap([], true),
+ 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(serviceName, caller) {
+ if (angular.isString(caller)) {
+ path.push(caller);
+ }
+ throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
+ })),
+ instanceCache = {},
+ instanceInjector = (instanceCache.$injector =
+ createInternalInjector(instanceCache, function(serviceName, caller) {
+ var provider = providerInjector.get(serviceName + providerSuffix, caller);
+ return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
+ }));
+
+
+ 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 enforceReturnValue(name, factory) {
+ return function enforcedReturnValue() {
+ var result = instanceInjector.invoke(factory, this);
+ if (isUndefined(result)) {
+ throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
+ }
+ return result;
+ };
+ }
+
+ function factory(name, factoryFn, enforce) {
+ return provider(name, {
+ $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
+ });
+ }
+
+ function service(name, constructor) {
+ return factory(name, ['$injector', function($injector) {
+ return $injector.instantiate(constructor);
+ }]);
+ }
+
+ function value(name, val) { return factory(name, valueFn(val), false); }
+
+ 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;
+ forEach(modulesToLoad, function(module) {
+ if (loadedModules.get(module)) return;
+ loadedModules.put(module, true);
+
+ function runInvokeQueue(queue) {
+ var i, ii;
+ for (i = 0, ii = queue.length; i < ii; i++) {
+ var invokeArgs = queue[i],
+ provider = providerInjector.get(invokeArgs[0]);
+
+ provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
+ }
+ }
+
+ try {
+ if (isString(module)) {
+ moduleFn = angularModule(module);
+ runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
+ runInvokeQueue(moduleFn._invokeQueue);
+ runInvokeQueue(moduleFn._configBlocks);
+ } 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, caller) {
+ if (cache.hasOwnProperty(serviceName)) {
+ if (cache[serviceName] === INSTANTIATING) {
+ throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
+ serviceName + ' <- ' + path.join(' <- '));
+ }
+ return cache[serviceName];
+ } else {
+ try {
+ path.unshift(serviceName);
+ cache[serviceName] = INSTANTIATING;
+ return cache[serviceName] = factory(serviceName, caller);
+ } catch (err) {
+ if (cache[serviceName] === INSTANTIATING) {
+ delete cache[serviceName];
+ }
+ throw err;
+ } finally {
+ path.shift();
+ }
+ }
+ }
+
+ function invoke(fn, self, locals, serviceName) {
+ if (typeof locals === 'string') {
+ serviceName = locals;
+ locals = null;
+ }
+
+ var args = [],
+ $inject = createInjector.$$annotate(fn, strictDi, serviceName),
+ 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, serviceName)
+ );
+ }
+ if (isArray(fn)) {
+ fn = fn[length];
+ }
+
+ // http://jsperf.com/angularjs-invoke-apply-vs-switch
+ // #5388
+ return fn.apply(self, args);
+ }
+
+ function instantiate(Type, locals, serviceName) {
+ // Check if Type is annotated and use just the given function at n-1 as parameter
+ // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
+ // Object creation: http://jsperf.com/create-constructor/2
+ var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
+ var returnedValue = invoke(Type, instance, locals, serviceName);
+
+ return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
+ }
+
+ return {
+ invoke: invoke,
+ instantiate: instantiate,
+ get: getService,
+ annotate: createInjector.$$annotate,
+ has: function(name) {
+ return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
+ }
+ };
+ }
+}
+
+createInjector.$$annotate = annotate;
+
+/**
+ * @ngdoc provider
+ * @name $anchorScrollProvider
+ *
+ * @description
+ * Use `$anchorScrollProvider` to disable automatic scrolling whenever
+ * {@link ng.$location#hash $location.hash()} changes.
+ */
+function $AnchorScrollProvider() {
+
+ var autoScrollingEnabled = true;
+
+ /**
+ * @ngdoc method
+ * @name $anchorScrollProvider#disableAutoScrolling
+ *
+ * @description
+ * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
+ * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
+ * Use this method to disable automatic scrolling.
+ *
+ * If automatic scrolling is disabled, one must explicitly call
+ * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
+ * current hash.
+ */
+ this.disableAutoScrolling = function() {
+ autoScrollingEnabled = false;
+ };
+
+ /**
+ * @ngdoc service
+ * @name $anchorScroll
+ * @kind function
+ * @requires $window
+ * @requires $location
+ * @requires $rootScope
+ *
+ * @description
+ * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and
+ * scrolls to the related element, according to the rules specified in the
+ * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
+ *
+ * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
+ * match any anchor whenever it changes. This can be disabled by calling
+ * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
+ *
+ * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
+ * vertical scroll-offset (either fixed or dynamic).
+ *
+ * @property {(number|function|jqLite)} yOffset
+ * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
+ * positioned elements at the top of the page, such as navbars, headers etc.
+ *
+ * `yOffset` can be specified in various ways:
+ * - **number**: A fixed number of pixels to be used as offset.<br /><br />
+ * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
+ * a number representing the offset (in pixels).<br /><br />
+ * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
+ * the top of the page to the element's bottom will be used as offset.<br />
+ * **Note**: The element will be taken into account only as long as its `position` is set to
+ * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
+ * their height and/or positioning according to the viewport's size.
+ *
+ * <br />
+ * <div class="alert alert-warning">
+ * In order for `yOffset` to work properly, scrolling should take place on the document's root and
+ * not some child element.
+ * </div>
+ *
+ * @example
+ <example module="anchorScrollExample">
+ <file name="index.html">
+ <div id="scrollArea" ng-controller="ScrollController">
+ <a ng-click="gotoBottom()">Go to bottom</a>
+ <a id="bottom"></a> You're at the bottom!
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('anchorScrollExample', [])
+ .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
+ function ($scope, $location, $anchorScroll) {
+ $scope.gotoBottom = function() {
+ // set the location.hash to the id of
+ // the element you wish to scroll to.
+ $location.hash('bottom');
+
+ // call $anchorScroll()
+ $anchorScroll();
+ };
+ }]);
+ </file>
+ <file name="style.css">
+ #scrollArea {
+ height: 280px;
+ overflow: auto;
+ }
+
+ #bottom {
+ display: block;
+ margin-top: 2000px;
+ }
+ </file>
+ </example>
+ *
+ * <hr />
+ * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
+ * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
+ *
+ * @example
+ <example module="anchorScrollOffsetExample">
+ <file name="index.html">
+ <div class="fixed-header" ng-controller="headerCtrl">
+ <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
+ Go to anchor {{x}}
+ </a>
+ </div>
+ <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
+ Anchor {{x}} of 5
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('anchorScrollOffsetExample', [])
+ .run(['$anchorScroll', function($anchorScroll) {
+ $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
+ }])
+ .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
+ function ($anchorScroll, $location, $scope) {
+ $scope.gotoAnchor = function(x) {
+ var newHash = 'anchor' + x;
+ if ($location.hash() !== newHash) {
+ // set the $location.hash to `newHash` and
+ // $anchorScroll will automatically scroll to it
+ $location.hash('anchor' + x);
+ } else {
+ // call $anchorScroll() explicitly,
+ // since $location.hash hasn't changed
+ $anchorScroll();
+ }
+ };
+ }
+ ]);
+ </file>
+ <file name="style.css">
+ body {
+ padding-top: 50px;
+ }
+
+ .anchor {
+ border: 2px dashed DarkOrchid;
+ padding: 10px 10px 200px 10px;
+ }
+
+ .fixed-header {
+ background-color: rgba(0, 0, 0, 0.2);
+ height: 50px;
+ position: fixed;
+ top: 0; left: 0; right: 0;
+ }
+
+ .fixed-header > a {
+ display: inline-block;
+ margin: 5px 15px;
+ }
+ </file>
+ </example>
+ */
+ this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
+ var document = $window.document;
+
+ // Helper function to get first anchor from a NodeList
+ // (using `Array#some()` instead of `angular#forEach()` since it's more performant
+ // and working in all supported browsers.)
+ function getFirstAnchor(list) {
+ var result = null;
+ Array.prototype.some.call(list, function(element) {
+ if (nodeName_(element) === 'a') {
+ result = element;
+ return true;
+ }
+ });
+ return result;
+ }
+
+ function getYOffset() {
+
+ var offset = scroll.yOffset;
+
+ if (isFunction(offset)) {
+ offset = offset();
+ } else if (isElement(offset)) {
+ var elem = offset[0];
+ var style = $window.getComputedStyle(elem);
+ if (style.position !== 'fixed') {
+ offset = 0;
+ } else {
+ offset = elem.getBoundingClientRect().bottom;
+ }
+ } else if (!isNumber(offset)) {
+ offset = 0;
+ }
+
+ return offset;
+ }
+
+ function scrollTo(elem) {
+ if (elem) {
+ elem.scrollIntoView();
+
+ var offset = getYOffset();
+
+ if (offset) {
+ // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
+ // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
+ // top of the viewport.
+ //
+ // IF the number of pixels from the top of `elem` to the end of the page's content is less
+ // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
+ // way down the page.
+ //
+ // This is often the case for elements near the bottom of the page.
+ //
+ // In such cases we do not need to scroll the whole `offset` up, just the difference between
+ // the top of the element and the offset, which is enough to align the top of `elem` at the
+ // desired position.
+ var elemTop = elem.getBoundingClientRect().top;
+ $window.scrollBy(0, elemTop - offset);
+ }
+ } else {
+ $window.scrollTo(0, 0);
+ }
+ }
+
+ function scroll() {
+ var hash = $location.hash(), elm;
+
+ // empty hash, scroll to the top of the page
+ if (!hash) scrollTo(null);
+
+ // element with given id
+ else if ((elm = document.getElementById(hash))) scrollTo(elm);
+
+ // first anchor with given name :-D
+ else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
+
+ // no element and hash == 'top', scroll to the top of the page
+ else if (hash === 'top') scrollTo(null);
+ }
+
+ // does not scroll when user clicks on anchor link that is currently on
+ // (no url change, no $location.hash() change), browser native does scroll
+ if (autoScrollingEnabled) {
+ $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
+ function autoScrollWatchAction(newVal, oldVal) {
+ // skip the initial scroll if $location.hash is empty
+ if (newVal === oldVal && newVal === '') return;
+
+ jqLiteDocumentLoaded(function() {
+ $rootScope.$evalAsync(scroll);
+ });
+ });
+ }
+
+ return scroll;
+ }];
+}
+
+var $animateMinErr = minErr('$animate');
+
+/**
+ * @ngdoc provider
+ * @name $animateProvider
+ *
+ * @description
+ * Default implementation of $animate that doesn't perform any animations, instead just
+ * synchronously performs DOM
+ * updates and calls done() callbacks.
+ *
+ * In order to enable animations the ngAnimate module has to be loaded.
+ *
+ * To see the functional implementation check out src/ngAnimate/animate.js
+ */
+var $AnimateProvider = ['$provide', function($provide) {
+
+
+ this.$$selectors = {};
+
+
+ /**
+ * @ngdoc method
+ * @name $animateProvider#register
+ *
+ * @description
+ * Registers a new injectable animation factory function. The factory function produces the
+ * animation object which contains callback functions for each event that is expected to be
+ * animated.
+ *
+ * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
+ * must be called once the element animation is complete. If a function is returned then the
+ * animation service will use this function to cancel the animation whenever a cancel event is
+ * triggered.
+ *
+ *
+ * ```js
+ * 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);
+ };
+
+ /**
+ * @ngdoc method
+ * @name $animateProvider#classNameFilter
+ *
+ * @description
+ * Sets and/or returns the CSS class regular expression that is checked when performing
+ * an animation. Upon bootstrap the classNameFilter value is not set at all and will
+ * therefore enable $animate to attempt to perform an animation on any element.
+ * When setting the classNameFilter value, animations will only be performed on elements
+ * that successfully match the filter expression. This in turn can boost performance
+ * for low-powered devices as well as applications containing a lot of structural operations.
+ * @param {RegExp=} expression The className expression which will be checked against all animations
+ * @return {RegExp} The current CSS className expression value. If null then there is no expression value
+ */
+ this.classNameFilter = function(expression) {
+ if (arguments.length === 1) {
+ this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
+ }
+ return this.$$classNameFilter;
+ };
+
+ this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {
+
+ var currentDefer;
+
+ function runAnimationPostDigest(fn) {
+ var cancelFn, defer = $$q.defer();
+ defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {
+ cancelFn && cancelFn();
+ };
+
+ $rootScope.$$postDigest(function ngAnimatePostDigest() {
+ cancelFn = fn(function ngAnimateNotifyComplete() {
+ defer.resolve();
+ });
+ });
+
+ return defer.promise;
+ }
+
+ function resolveElementClasses(element, classes) {
+ var toAdd = [], toRemove = [];
+
+ var hasClasses = createMap();
+ forEach((element.attr('class') || '').split(/\s+/), function(className) {
+ hasClasses[className] = true;
+ });
+
+ forEach(classes, function(status, className) {
+ var hasClass = hasClasses[className];
+
+ // If the most recent class manipulation (via $animate) was to remove the class, and the
+ // element currently has the class, the class is scheduled for removal. Otherwise, if
+ // the most recent class manipulation (via $animate) was to add the class, and the
+ // element does not currently have the class, the class is scheduled to be added.
+ if (status === false && hasClass) {
+ toRemove.push(className);
+ } else if (status === true && !hasClass) {
+ toAdd.push(className);
+ }
+ });
+
+ return (toAdd.length + toRemove.length) > 0 &&
+ [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];
+ }
+
+ function cachedClassManipulation(cache, classes, op) {
+ for (var i=0, ii = classes.length; i < ii; ++i) {
+ var className = classes[i];
+ cache[className] = op;
+ }
+ }
+
+ function asyncPromise() {
+ // only serve one instance of a promise in order to save CPU cycles
+ if (!currentDefer) {
+ currentDefer = $$q.defer();
+ $$asyncCallback(function() {
+ currentDefer.resolve();
+ currentDefer = null;
+ });
+ }
+ return currentDefer.promise;
+ }
+
+ function applyStyles(element, options) {
+ if (angular.isObject(options)) {
+ var styles = extend(options.from || {}, options.to || {});
+ element.css(styles);
+ }
+ }
+
+ /**
+ *
+ * @ngdoc service
+ * @name $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 {
+ animate: function(element, from, to) {
+ applyStyles(element, { from: from, to: to });
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#enter
+ * @kind function
+ * @description Inserts the element into the DOM either after the `after` element or
+ * as the first child within the `parent` element. When the function is called a promise
+ * is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will be inserted into the DOM
+ * @param {DOMElement} parent the parent element which will append the element as
+ * a child (if the after element is not present)
+ * @param {DOMElement} after the sibling element which will append the element
+ * after itself
+ * @param {object=} options an optional collection of styles that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ enter: function(element, parent, after, options) {
+ applyStyles(element, options);
+ after ? after.after(element)
+ : parent.prepend(element);
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#leave
+ * @kind function
+ * @description Removes the element from the DOM. When the function is called a promise
+ * is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will be removed from the DOM
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ leave: function(element, options) {
+ applyStyles(element, options);
+ element.remove();
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#move
+ * @kind 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. When the function
+ * is called a promise is returned that will be resolved at a later time.
+ *
+ * @param {DOMElement} element the element which will be moved around within the
+ * DOM
+ * @param {DOMElement} parent the parent element where the element will be
+ * inserted into (if the after element is not present)
+ * @param {DOMElement} after the sibling element where the element will be
+ * positioned next to
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ move: function(element, parent, after, options) {
+ // Do not remove element before insert. Removing will cause data associated with the
+ // element to be dropped. Insert will implicitly do the remove.
+ return this.enter(element, parent, after, options);
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#addClass
+ * @kind function
+ * @description Adds the provided className CSS class value to the provided element.
+ * When the function is called a promise is returned that will be resolved at a later time.
+ * @param {DOMElement} 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 {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ addClass: function(element, className, options) {
+ return this.setClass(element, className, [], options);
+ },
+
+ $$addClassImmediately: function(element, className, options) {
+ element = jqLite(element);
+ className = !isString(className)
+ ? (isArray(className) ? className.join(' ') : '')
+ : className;
+ forEach(element, function(element) {
+ jqLiteAddClass(element, className);
+ });
+ applyStyles(element, options);
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#removeClass
+ * @kind function
+ * @description Removes the provided className CSS class value from the provided element.
+ * When the function is called a promise is returned that will be resolved at a later time.
+ * @param {DOMElement} 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 {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ removeClass: function(element, className, options) {
+ return this.setClass(element, [], className, options);
+ },
+
+ $$removeClassImmediately: function(element, className, options) {
+ element = jqLite(element);
+ className = !isString(className)
+ ? (isArray(className) ? className.join(' ') : '')
+ : className;
+ forEach(element, function(element) {
+ jqLiteRemoveClass(element, className);
+ });
+ applyStyles(element, options);
+ return asyncPromise();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#setClass
+ * @kind function
+ * @description Adds and/or removes the given CSS classes to and from the element.
+ * When the function is called a promise is returned that will be resolved at a later time.
+ * @param {DOMElement} element the element which will have its CSS classes changed
+ * removed from it
+ * @param {string} add the CSS classes which will be added to the element
+ * @param {string} remove the CSS class which will be removed from the element
+ * @param {object=} options an optional collection of options that will be applied to the element.
+ * @return {Promise} the animation callback promise
+ */
+ setClass: function(element, add, remove, options) {
+ var self = this;
+ var STORAGE_KEY = '$$animateClasses';
+ var createdCache = false;
+ element = jqLite(element);
+
+ var cache = element.data(STORAGE_KEY);
+ if (!cache) {
+ cache = {
+ classes: {},
+ options: options
+ };
+ createdCache = true;
+ } else if (options && cache.options) {
+ cache.options = angular.extend(cache.options || {}, options);
+ }
+
+ var classes = cache.classes;
+
+ add = isArray(add) ? add : add.split(' ');
+ remove = isArray(remove) ? remove : remove.split(' ');
+ cachedClassManipulation(classes, add, true);
+ cachedClassManipulation(classes, remove, false);
+
+ if (createdCache) {
+ cache.promise = runAnimationPostDigest(function(done) {
+ var cache = element.data(STORAGE_KEY);
+ element.removeData(STORAGE_KEY);
+
+ // in the event that the element is removed before postDigest
+ // is run then the cache will be undefined and there will be
+ // no need anymore to add or remove and of the element classes
+ if (cache) {
+ var classes = resolveElementClasses(element, cache.classes);
+ if (classes) {
+ self.$$setClassImmediately(element, classes[0], classes[1], cache.options);
+ }
+ }
+
+ done();
+ });
+ element.data(STORAGE_KEY, cache);
+ }
+
+ return cache.promise;
+ },
+
+ $$setClassImmediately: function(element, add, remove, options) {
+ add && this.$$addClassImmediately(element, add);
+ remove && this.$$removeClassImmediately(element, remove);
+ applyStyles(element, options);
+ return asyncPromise();
+ },
+
+ enabled: noop,
+ cancel: noop
+ };
+ }];
+}];
+
+function $$AsyncCallbackProvider() {
+ this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
+ return $$rAF.supported
+ ? function(fn) { return $$rAF(fn); }
+ : function(fn) {
+ return $timeout(fn, 0, false);
+ };
+ }];
+}
+
+/* global stripHash: true */
+
+/**
+ * ! This is a private undocumented service !
+ *
+ * @name $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 {object} $log window.console 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);
+ }
+ }
+ }
+ }
+ }
+
+ function getHash(url) {
+ var index = url.indexOf('#');
+ return index === -1 ? '' : url.substr(index);
+ }
+
+ /**
+ * @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 $browser#addPollFn
+ *
+ * @param {function()} fn Poll function to add
+ *
+ * @description
+ * Adds a function to the list of functions that poller periodically executes,
+ * and starts polling if not started yet.
+ *
+ * @returns {function()} the added function
+ */
+ self.addPollFn = function(fn) {
+ if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
+ pollFns.push(fn);
+ return fn;
+ };
+
+ /**
+ * @param {number} interval How often should browser call poll functions (ms)
+ * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
+ *
+ * @description
+ * Configures the poller to run in the specified intervals, using the specified
+ * setTimeout fn and kicks it off.
+ */
+ function startPoller(interval, setTimeout) {
+ (function check() {
+ forEach(pollFns, function(pollFn) { pollFn(); });
+ pollTimeout = setTimeout(check, interval);
+ })();
+ }
+
+ //////////////////////////////////////////////////////////////
+ // URL API
+ //////////////////////////////////////////////////////////////
+
+ var cachedState, lastHistoryState,
+ lastBrowserUrl = location.href,
+ baseElement = document.find('base'),
+ reloadLocation = null;
+
+ cacheState();
+ lastHistoryState = cachedState;
+
+ /**
+ * @name $browser#url
+ *
+ * @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?
+ * @param {object=} state object to use with pushState/replaceState
+ */
+ self.url = function(url, replace, state) {
+ // In modern browsers `history.state` is `null` by default; treating it separately
+ // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
+ // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
+ if (isUndefined(state)) {
+ state = null;
+ }
+
+ // Android Browser BFCache causes location, history reference to become stale.
+ if (location !== window.location) location = window.location;
+ if (history !== window.history) history = window.history;
+
+ // setter
+ if (url) {
+ var sameState = lastHistoryState === state;
+
+ // Don't change anything if previous and current URLs and states match. This also prevents
+ // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
+ // See https://github.com/angular/angular.js/commit/ffb2701
+ if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
+ return self;
+ }
+ var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
+ lastBrowserUrl = url;
+ lastHistoryState = state;
+ // Don't use history API if only the hash changed
+ // due to a bug in IE10/IE11 which leads
+ // to not firing a `hashchange` nor `popstate` event
+ // in some cases (see #9143).
+ if ($sniffer.history && (!sameBase || !sameState)) {
+ history[replace ? 'replaceState' : 'pushState'](state, '', url);
+ cacheState();
+ // Do the assignment again so that those two variables are referentially identical.
+ lastHistoryState = cachedState;
+ } else {
+ if (!sameBase || reloadLocation) {
+ reloadLocation = url;
+ }
+ if (replace) {
+ location.replace(url);
+ } else if (!sameBase) {
+ location.href = url;
+ } else {
+ location.hash = getHash(url);
+ }
+ }
+ return self;
+ // getter
+ } else {
+ // - reloadLocation is needed as browsers don't allow to read out
+ // the new location.href if a reload happened.
+ // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
+ return reloadLocation || location.href.replace(/%27/g,"'");
+ }
+ };
+
+ /**
+ * @name $browser#state
+ *
+ * @description
+ * This method is a getter.
+ *
+ * Return history.state or null if history.state is undefined.
+ *
+ * @returns {object} state
+ */
+ self.state = function() {
+ return cachedState;
+ };
+
+ var urlChangeListeners = [],
+ urlChangeInit = false;
+
+ function cacheStateAndFireUrlChange() {
+ cacheState();
+ fireUrlChange();
+ }
+
+ function getCurrentState() {
+ try {
+ return history.state;
+ } catch (e) {
+ // MSIE can reportedly throw when there is no state (UNCONFIRMED).
+ }
+ }
+
+ // This variable should be used *only* inside the cacheState function.
+ var lastCachedState = null;
+ function cacheState() {
+ // This should be the only place in $browser where `history.state` is read.
+ cachedState = getCurrentState();
+ cachedState = isUndefined(cachedState) ? null : cachedState;
+
+ // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
+ if (equals(cachedState, lastCachedState)) {
+ cachedState = lastCachedState;
+ }
+ lastCachedState = cachedState;
+ }
+
+ function fireUrlChange() {
+ if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
+ return;
+ }
+
+ lastBrowserUrl = self.url();
+ lastHistoryState = cachedState;
+ forEach(urlChangeListeners, function(listener) {
+ listener(self.url(), cachedState);
+ });
+ }
+
+ /**
+ * @name $browser#onUrlChange
+ *
+ * @description
+ * Register callback function that will be called, when url changes.
+ *
+ * It's only called when the url is changed from 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) {
+ // TODO(vojta): refactor to use node's syntax for events
+ if (!urlChangeInit) {
+ // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
+ // don't fire popstate when user change the address bar and don't fire hashchange when url
+ // changed by push/replaceState
+
+ // html5 history api - popstate event
+ if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
+ // hashchange event
+ jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
+
+ urlChangeInit = true;
+ }
+
+ urlChangeListeners.push(callback);
+ return callback;
+ };
+
+ /**
+ * Checks whether the url has changed outside of Angular.
+ * Needs to be exported to be able to check for changes that have been done in sync,
+ * as hashchange/popstate events fire in async.
+ */
+ self.$$checkUrlChange = fireUrlChange;
+
+ //////////////////////////////////////////////////////////////
+ // Misc API
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * @name $browser#baseHref
+ *
+ * @description
+ * Returns current <base href>
+ * (always relative - without domain)
+ *
+ * @returns {string} The current base href
+ */
+ self.baseHref = function() {
+ var href = baseElement.attr('href');
+ return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
+ };
+
+ //////////////////////////////////////////////////////////////
+ // Cookies API
+ //////////////////////////////////////////////////////////////
+ var lastCookies = {};
+ var lastCookieString = '';
+ var cookiePath = self.baseHref();
+
+ function safeDecodeURIComponent(str) {
+ try {
+ return decodeURIComponent(str);
+ } catch (e) {
+ return str;
+ }
+ }
+
+ /**
+ * @name $browser#cookies
+ *
+ * @param {string=} name Cookie name
+ * @param {string=} value Cookie value
+ *
+ * @description
+ * The cookies method provides a 'private' low level access to browser cookies.
+ * It is not meant to be used directly, use the $cookie service instead.
+ *
+ * The return values vary depending on the arguments that the method was called with as follows:
+ *
+ * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
+ * it
+ * - cookies(name, value) -> set name to value, if value is undefined delete the cookie
+ * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
+ * way)
+ *
+ * @returns {Object} Hash of all cookies (if called without any parameter)
+ */
+ self.cookies = function(name, value) {
+ var cookieLength, cookieArray, cookie, i, index;
+
+ if (name) {
+ if (value === undefined) {
+ rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath +
+ ";expires=Thu, 01 Jan 1970 00:00:00 GMT";
+ } else {
+ if (isString(value)) {
+ cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +
+ ';path=' + cookiePath).length + 1;
+
+ // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
+ // - 300 cookies
+ // - 20 cookies per unique domain
+ // - 4096 bytes per cookie
+ if (cookieLength > 4096) {
+ $log.warn("Cookie '" + name +
+ "' possibly not set or overflowed because it was too large (" +
+ cookieLength + " > 4096 bytes)!");
+ }
+ }
+ }
+ } else {
+ if (rawDocument.cookie !== lastCookieString) {
+ lastCookieString = rawDocument.cookie;
+ cookieArray = lastCookieString.split("; ");
+ lastCookies = {};
+
+ for (i = 0; i < cookieArray.length; i++) {
+ cookie = cookieArray[i];
+ index = cookie.indexOf('=');
+ if (index > 0) { //ignore nameless cookies
+ name = safeDecodeURIComponent(cookie.substring(0, index));
+ // the first value that is seen for a cookie is the most
+ // specific one. values for the same cookie name that
+ // follow are for less specific paths.
+ if (lastCookies[name] === undefined) {
+ lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
+ }
+ }
+ }
+ }
+ return lastCookies;
+ }
+ };
+
+
+ /**
+ * @name $browser#defer
+ * @param {function()} fn A function, who's execution should be deferred.
+ * @param {number=} [delay=0] of milliseconds to defer the function execution.
+ * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
+ *
+ * @description
+ * Executes a fn asynchronously via `setTimeout(fn, delay)`.
+ *
+ * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
+ * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
+ * via `$browser.defer.flush()`.
+ *
+ */
+ self.defer = function(fn, delay) {
+ var timeoutId;
+ outstandingRequestCount++;
+ timeoutId = setTimeout(function() {
+ delete pendingDeferIds[timeoutId];
+ completeOutstandingRequest(fn);
+ }, delay || 0);
+ pendingDeferIds[timeoutId] = true;
+ return timeoutId;
+ };
+
+
+ /**
+ * @name $browser#defer.cancel
+ *
+ * @description
+ * Cancels a deferred task identified with `deferId`.
+ *
+ * @param {*} deferId Token returned by the `$browser.defer` function.
+ * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
+ * canceled.
+ */
+ self.defer.cancel = function(deferId) {
+ if (pendingDeferIds[deferId]) {
+ delete pendingDeferIds[deferId];
+ clearTimeout(deferId);
+ completeOutstandingRequest(noop);
+ return true;
+ }
+ return false;
+ };
+
+}
+
+function $BrowserProvider() {
+ this.$get = ['$window', '$log', '$sniffer', '$document',
+ function($window, $log, $sniffer, $document) {
+ return new Browser($window, $document, $log, $sniffer);
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $cacheFactory
+ *
+ * @description
+ * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
+ * them.
+ *
+ * ```js
+ *
+ * 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.
+ *
+ * @example
+ <example module="cacheExampleApp">
+ <file name="index.html">
+ <div ng-controller="CacheController">
+ <input ng-model="newCacheKey" placeholder="Key">
+ <input ng-model="newCacheValue" placeholder="Value">
+ <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
+
+ <p ng-if="keys.length">Cached Values</p>
+ <div ng-repeat="key in keys">
+ <span ng-bind="key"></span>
+ <span>: </span>
+ <b ng-bind="cache.get(key)"></b>
+ </div>
+
+ <p>Cache Info</p>
+ <div ng-repeat="(key, value) in cache.info()">
+ <span ng-bind="key"></span>
+ <span>: </span>
+ <b ng-bind="value"></b>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('cacheExampleApp', []).
+ controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
+ $scope.keys = [];
+ $scope.cache = $cacheFactory('cacheId');
+ $scope.put = function(key, value) {
+ if ($scope.cache.get(key) === undefined) {
+ $scope.keys.push(key);
+ }
+ $scope.cache.put(key, value === undefined ? null : value);
+ };
+ }]);
+ </file>
+ <file name="style.css">
+ p {
+ margin: 10px 0 3px;
+ }
+ </file>
+ </example>
+ */
+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;
+
+ /**
+ * @ngdoc type
+ * @name $cacheFactory.Cache
+ *
+ * @description
+ * A cache object used to store and retrieve data, primarily used by
+ * {@link $http $http} and the {@link ng.directive:script script} directive to cache
+ * templates and other data.
+ *
+ * ```js
+ * angular.module('superCache')
+ * .factory('superCache', ['$cacheFactory', function($cacheFactory) {
+ * return $cacheFactory('super-cache');
+ * }]);
+ * ```
+ *
+ * Example test:
+ *
+ * ```js
+ * it('should behave like a cache', inject(function(superCache) {
+ * superCache.put('key', 'value');
+ * superCache.put('another key', 'another value');
+ *
+ * expect(superCache.info()).toEqual({
+ * id: 'super-cache',
+ * size: 2
+ * });
+ *
+ * superCache.remove('another key');
+ * expect(superCache.get('another key')).toBeUndefined();
+ *
+ * superCache.removeAll();
+ * expect(superCache.info()).toEqual({
+ * id: 'super-cache',
+ * size: 0
+ * });
+ * }));
+ * ```
+ */
+ return caches[cacheId] = {
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#put
+ * @kind function
+ *
+ * @description
+ * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
+ * retrieved later, and incrementing the size of the cache if the key was not already
+ * present in the cache. If behaving like an LRU cache, it will also remove stale
+ * entries from the set.
+ *
+ * It will not insert undefined values into the cache.
+ *
+ * @param {string} key the key under which the cached data is stored.
+ * @param {*} value the value to store alongside the key. If it is undefined, the key
+ * will not be stored.
+ * @returns {*} the value stored.
+ */
+ put: function(key, value) {
+ if (capacity < Number.MAX_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;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#get
+ * @kind function
+ *
+ * @description
+ * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
+ *
+ * @param {string} key the key of the data to be retrieved
+ * @returns {*} the value stored.
+ */
+ get: function(key) {
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
+
+ refresh(lruEntry);
+ }
+
+ return data[key];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#remove
+ * @kind function
+ *
+ * @description
+ * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
+ *
+ * @param {string} key the key of the entry to be removed
+ */
+ remove: function(key) {
+ if (capacity < Number.MAX_VALUE) {
+ 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--;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#removeAll
+ * @kind function
+ *
+ * @description
+ * Clears the cache object of any entries.
+ */
+ removeAll: function() {
+ data = {};
+ size = 0;
+ lruHash = {};
+ freshEnd = staleEnd = null;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#destroy
+ * @kind function
+ *
+ * @description
+ * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
+ * removing it from the {@link $cacheFactory $cacheFactory} set.
+ */
+ destroy: function() {
+ data = null;
+ stats = null;
+ lruHash = null;
+ delete caches[cacheId];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#info
+ * @kind function
+ *
+ * @description
+ * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
+ *
+ * @returns {object} an object with the following properties:
+ * <ul>
+ * <li>**id**: the id of the cache instance</li>
+ * <li>**size**: the number of entries kept in the cache instance</li>
+ * <li>**...**: any additional properties from the options object when creating the
+ * cache.</li>
+ * </ul>
+ */
+ 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 $cacheFactory#info
+ *
+ * @description
+ * Get information about all 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 $cacheFactory#get
+ *
+ * @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 service
+ * @name $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:
+ *
+ * ```html
+ * <script type="text/ng-template" id="templateId.html">
+ * <p>This is the content of the template</p>
+ * </script>
+ * ```
+ *
+ * **Note:** the `script` tag containing the template does not need to be included in the `head` of
+ * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
+ * element with ng-app attribute), otherwise the template will be ignored.
+ *
+ * Adding via the `$templateCache` service:
+ *
+ * ```js
+ * var myApp = angular.module('myApp', []);
+ * myApp.run(function($templateCache) {
+ * $templateCache.put('templateId.html', 'This is the content of the template');
+ * });
+ * ```
+ *
+ * To retrieve the template later, simply use it in your HTML:
+ * ```html
+ * <div ng-include=" 'templateId.html' "></div>
+ * ```
+ *
+ * or get it via Javascript:
+ * ```js
+ * $templateCache.get('templateId.html')
+ * ```
+ *
+ * See {@link ng.$cacheFactory $cacheFactory}.
+ *
+ */
+function $TemplateCacheProvider() {
+ this.$get = ['$cacheFactory', function($cacheFactory) {
+ return $cacheFactory('templates');
+ }];
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
+ *
+ * DOM-related variables:
+ *
+ * - "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 service
+ * @name $compile
+ * @kind function
+ *
+ * @description
+ * Compiles an HTML string or DOM into a template and produces a template function, which
+ * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
+ *
+ * The compilation is a process of walking the DOM tree and matching DOM elements to
+ * {@link ng.$compileProvider#directive directives}.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** This document is an in-depth reference of all directive options.
+ * For a gentle introduction to directives with examples of common use cases,
+ * see the {@link guide/directive directive guide}.
+ * </div>
+ *
+ * ## Comprehensive Directive API
+ *
+ * There are many different options for a directive.
+ *
+ * The difference resides in the return value of the factory function.
+ * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
+ * or just the `postLink` function (all other properties will have the default values).
+ *
+ * <div class="alert alert-success">
+ * **Best Practice:** It's recommended to use the "directive definition object" form.
+ * </div>
+ *
+ * Here's an example directive declared with a Directive Definition Object:
+ *
+ * ```js
+ * var myModule = angular.module(...);
+ *
+ * myModule.directive('directiveName', function factory(injectables) {
+ * var directiveDefinitionObject = {
+ * priority: 0,
+ * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
+ * // or
+ * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
+ * transclude: false,
+ * restrict: 'A',
+ * templateNamespace: 'html',
+ * scope: false,
+ * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
+ * controllerAs: 'stringIdentifier',
+ * bindToController: false,
+ * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
+ * compile: function compile(tElement, tAttrs, transclude) {
+ * return {
+ * 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;
+ * });
+ * ```
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Any unspecified options will use the default value. You can see the default values below.
+ * </div>
+ *
+ * Therefore the above can be simplified as:
+ *
+ * ```js
+ * 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 ng.$compile
+ * compiler}. The attributes are:
+ *
+ * #### `multiElement`
+ * When this property is set to true, the HTML compiler will collect DOM nodes between
+ * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
+ * together as the directive elements. It is recommended that this feature be used on directives
+ * which are not strictly behavioural (such as {@link ngClick}), and which
+ * do not manipulate or replace child nodes (such as {@link ngInclude}).
+ *
+ * #### `priority`
+ * When there are multiple directives defined on a single DOM element, sometimes it
+ * is necessary to specify the order in which the directives are applied. The `priority` is used
+ * to sort the directives before their `compile` functions get called. Priority is defined as a
+ * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
+ * are also run in priority order, but post-link functions are run in reverse order. 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). Note that expressions
+ * and other directives used in the directive's template will also be excluded from execution.
+ *
+ * #### `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 `<widget my-attr="hello {{name}}">` and widget definition
+ * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
+ * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
+ * `localName` property on the widget scope. The `name` is read from the parent scope (not
+ * component scope).
+ *
+ * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
+ * parent scope property of name defined via the value of the `attr` attribute. If no `attr`
+ * name is specified then the attribute name is assumed to be the same as the local name.
+ * Given `<widget my-attr="parentModel">` and widget definition of
+ * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
+ * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
+ * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
+ * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
+ * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
+ * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
+ * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
+ *
+ * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
+ * If no `attr` name is specified then the attribute name is assumed to be the same as the
+ * local name. Given `<widget my-attr="count = count + value">` and widget definition of
+ * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
+ * a function wrapper for the `count = count + value` expression. Often it's desirable to
+ * pass data from the isolated scope via an expression to the parent scope, this can be
+ * done by passing a map of local variable names and values into the expression wrapper fn.
+ * For example, if the expression is `increment(amount)` then we can specify the amount value
+ * by calling the `localFn` as `localFn({amount: 22})`.
+ *
+ *
+ * #### `bindToController`
+ * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
+ * allow a component to have its properties bound to the controller, rather than to scope. When the controller
+ * is instantiated, the initial values of the isolate scope bindings are already available.
+ *
+ * #### `controller`
+ * Controller constructor function. The controller is instantiated before the
+ * pre-linking phase and it is shared with other directives (see
+ * `require` attribute). This allows the directives to communicate with each other and augment
+ * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
+ *
+ * * `$scope` - Current scope associated with the element
+ * * `$element` - Current element
+ * * `$attrs` - Current attributes object for the element
+ * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
+ * `function([scope], cloneLinkingFn, futureParentElement)`.
+ * * `scope`: optional argument to override the scope.
+ * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.
+ * * `futureParentElement`:
+ * * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
+ * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
+ * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
+ * and when the `cloneLinkinFn` is passed,
+ * as those elements need to created and cloned in a special way when they are defined outside their
+ * usual containers (e.g. like `<svg>`).
+ * * See also the `directive.templateNamespace` property.
+ *
+ *
+ * #### `require`
+ * Require another directive and inject its controller as the fourth argument to the linking function. The
+ * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
+ * injected argument will be an array in corresponding order. If no such directive can be
+ * found, or if the directive does not have a controller, then an error is raised (unless no link function
+ * is specified, in which case error checking is skipped). The name can be prefixed with:
+ *
+ * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
+ * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
+ * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
+ * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.
+ * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
+ * `null` to the `link` fn if not found.
+ * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass
+ * `null` to the `link` fn if not found.
+ *
+ *
+ * #### `controllerAs`
+ * Controller alias at the directive scope. An alias for the controller so it
+ * can be referenced at the directive template. The directive needs to define a scope for this
+ * configuration to be used. Useful in the case when directive is used as component.
+ *
+ *
+ * #### `restrict`
+ * String of subset of `EACM` which restricts the directive to a specific directive
+ * declaration style. If omitted, the defaults (elements and attributes) are used.
+ *
+ * * `E` - Element name (default): `<my-directive></my-directive>`
+ * * `A` - Attribute (default): `<div my-directive="exp"></div>`
+ * * `C` - Class: `<div class="my-directive: exp;"></div>`
+ * * `M` - Comment: `<!-- directive: my-directive exp -->`
+ *
+ *
+ * #### `templateNamespace`
+ * String representing the document type used by the markup in the template.
+ * AngularJS needs this information as those elements need to be created and cloned
+ * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.
+ *
+ * * `html` - All root nodes in the template are HTML. Root nodes may also be
+ * top-level elements such as `<svg>` or `<math>`.
+ * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).
+ * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).
+ *
+ * If no `templateNamespace` is specified, then the namespace is considered to be `html`.
+ *
+ * #### `template`
+ * HTML markup that may:
+ * * Replace the contents of the directive's element (default).
+ * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
+ * * Wrap the contents of the directive's element (if `transclude` is true).
+ *
+ * Value may be:
+ *
+ * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
+ * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
+ * function api below) and returns a string value.
+ *
+ *
+ * #### `templateUrl`
+ * This is similar to `template` but the template is loaded from the specified URL, asynchronously.
+ *
+ * Because template loading is asynchronous the compiler will suspend compilation of directives on that element
+ * for later when the template has been resolved. In the meantime it will continue to compile and link
+ * sibling and parent elements as though this element had not contained any directives.
+ *
+ * The compiler does not suspend the entire compilation to wait for templates to be loaded because this
+ * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the
+ * case when only one deeply nested directive has `templateUrl`.
+ *
+ * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
+ *
+ * You can specify `templateUrl` as a string representing the URL or as a function which takes two
+ * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
+ * a string value representing the url. In either case, the template URL is passed through {@link
+ * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
+ *
+ *
+ * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
+ * specify what the template should replace. Defaults to `false`.
+ *
+ * * `true` - the template will replace the directive's element.
+ * * `false` - the template will replace the contents of the directive's element.
+ *
+ * The replacement process migrates all of the attributes / classes from the old element to the new
+ * one. See the {@link guide/directive#template-expanding-directive
+ * Directives Guide} for an example.
+ *
+ * There are very few scenarios where element replacement is required for the application function,
+ * the main one being reusable custom components that are used within SVG contexts
+ * (because SVG doesn't work with custom elements in the DOM tree).
+ *
+ * #### `transclude`
+ * Extract the contents of the element where the directive appears and make it available to the directive.
+ * The contents are compiled and provided to the directive as a **transclusion function**. See the
+ * {@link $compile#transclusion Transclusion} section below.
+ *
+ * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
+ * directive's element or the entire element:
+ *
+ * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
+ * * `'element'` - transclude the whole of the directive's element including any directives on this
+ * element that defined at a lower priority than this directive. When used, the `template`
+ * property is ignored.
+ *
+ *
+ * #### `compile`
+ *
+ * ```js
+ * 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. 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` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
+ *
+ * <div class="alert alert-warning">
+ * **Note:** The template instance and the link instance may be different objects if the template has
+ * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
+ * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
+ * should be done in a linking function rather than in a compile function.
+ * </div>
+
+ * <div class="alert alert-warning">
+ * **Note:** The compile function cannot handle directives that recursively use themselves in their
+ * own templates or compile functions. Compiling these directives results in an infinite loop and a
+ * stack overflow errors.
+ *
+ * This can be avoided by manually using $compile in the postLink function to imperatively compile
+ * a directive's template instead of relying on automatic template compilation via `template` or
+ * `templateUrl` declaration or manual compilation inside the compile function.
+ * </div>
+ *
+ * <div class="alert alert-error">
+ * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
+ * e.g. does not know about the right outer scope. Please use the transclude function that is passed
+ * to the link function instead.
+ * </div>
+
+ * A compile function can have a return value which can be either a function or an object.
+ *
+ * * returning a (post-link) function - is equivalent to registering the linking function via the
+ * `link` property of the config object when the compile function is empty.
+ *
+ * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
+ * control when a linking function should be called during the linking phase. See info about
+ * pre-linking and post-linking functions below.
+ *
+ *
+ * #### `link`
+ * This property is used only if the `compile` property is not defined.
+ *
+ * ```js
+ * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
+ * ```
+ *
+ * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
+ * executed after the template has been cloned. This is where most of the directive logic will be
+ * put.
+ *
+ * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
+ * directive for registering {@link ng.$rootScope.Scope#$watch watches}.
+ *
+ * * `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` - the directive's required controller instance(s) - Instances are shared
+ * among all directives, which allows the directives to use the controllers as a communication
+ * channel. The exact value depends on the directive's `require` property:
+ * * `string`: the controller instance
+ * * `array`: array of controller instances
+ * * no controller(s) required: `undefined`
+ *
+ * If a required controller cannot be found, and it is optional, the instance is `null`,
+ * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
+ *
+ * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
+ * This is the same as the `$transclude`
+ * parameter of directive controllers, see there for details.
+ * `function([scope], cloneLinkingFn, futureParentElement)`.
+ *
+ * #### 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.
+ *
+ * Note that child elements that contain `templateUrl` directives will not have been compiled
+ * and linked since they are waiting for their template to load asynchronously and their own
+ * compilation and linking has been suspended until that occurs.
+ *
+ * It is safe to do DOM transformation in the post-linking function on elements that are not waiting
+ * for their async templates to be resolved.
+ *
+ *
+ * ### Transclusion
+ *
+ * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
+ * copying them to another part of the DOM, while maintaining their connection to the original AngularJS
+ * scope from where they were taken.
+ *
+ * Transclusion is used (often with {@link ngTransclude}) to insert the
+ * original contents of a directive's element into a specified place in the template of the directive.
+ * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded
+ * content has access to the properties on the scope from which it was taken, even if the directive
+ * has isolated scope.
+ * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.
+ *
+ * This makes it possible for the widget to have private state for its template, while the transcluded
+ * content has access to its originating scope.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** When testing an element transclude directive you must not place the directive at the root of the
+ * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
+ * Testing Transclusion Directives}.
+ * </div>
+ *
+ * #### Transclusion Functions
+ *
+ * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
+ * function** to the directive's `link` function and `controller`. This transclusion function is a special
+ * **linking function** that will return the compiled contents linked to a new transclusion scope.
+ *
+ * <div class="alert alert-info">
+ * If you are just using {@link ngTransclude} then you don't need to worry about this function, since
+ * ngTransclude will deal with it for us.
+ * </div>
+ *
+ * If you want to manually control the insertion and removal of the transcluded content in your directive
+ * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
+ * object that contains the compiled DOM, which is linked to the correct transclusion scope.
+ *
+ * When you call a transclusion function you can pass in a **clone attach function**. This function accepts
+ * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
+ * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
+ *
+ * <div class="alert alert-info">
+ * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
+ * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
+ * </div>
+ *
+ * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone
+ * attach function**:
+ *
+ * ```js
+ * var transcludedContent, transclusionScope;
+ *
+ * $transclude(function(clone, scope) {
+ * element.append(clone);
+ * transcludedContent = clone;
+ * transclusionScope = scope;
+ * });
+ * ```
+ *
+ * Later, if you want to remove the transcluded content from your DOM then you should also destroy the
+ * associated transclusion scope:
+ *
+ * ```js
+ * transcludedContent.remove();
+ * transclusionScope.$destroy();
+ * ```
+ *
+ * <div class="alert alert-info">
+ * **Best Practice**: if you intend to add and remove transcluded content manually in your directive
+ * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it),
+ * then you are also responsible for calling `$destroy` on the transclusion scope.
+ * </div>
+ *
+ * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
+ * automatically destroy their transluded clones as necessary so you do not need to worry about this if
+ * you are simply using {@link ngTransclude} to inject the transclusion into your directive.
+ *
+ *
+ * #### Transclusion Scopes
+ *
+ * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion
+ * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed
+ * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it
+ * was taken.
+ *
+ * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look
+ * like this:
+ *
+ * ```html
+ * <div ng-app>
+ * <div isolate>
+ * <div transclusion>
+ * </div>
+ * </div>
+ * </div>
+ * ```
+ *
+ * The `$parent` scope hierarchy will look like this:
+ *
+ * ```
+ * - $rootScope
+ * - isolate
+ * - transclusion
+ * ```
+ *
+ * but the scopes will inherit prototypically from different scopes to their `$parent`.
+ *
+ * ```
+ * - $rootScope
+ * - transclusion
+ * - isolate
+ * ```
+ *
+ *
+ * ### Attributes
+ *
+ * The {@link 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`.
+ *
+ * ```js
+ * 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);
+ * });
+ * }
+ * ```
+ *
+ * ## Example
+ *
+ * <div class="alert alert-warning">
+ * **Note**: Typically directives are registered with `module.directive`. The example below is
+ * to illustrate how `$compile` works.
+ * </div>
+ *
+ <example module="compileExample">
+ <file name="index.html">
+ <script>
+ angular.module('compileExample', [], function($compileProvider) {
+ // configure new 'compile' directive by passing a directive
+ // factory function. The factory function injects the '$compile'
+ $compileProvider.directive('compile', function($compile) {
+ // directive factory creates a link function
+ return function(scope, element, attrs) {
+ scope.$watch(
+ function(scope) {
+ // watch the 'compile' expression for changes
+ return scope.$eval(attrs.compile);
+ },
+ function(value) {
+ // when the 'compile' expression changes
+ // assign it into the current DOM
+ element.html(value);
+
+ // compile the new DOM and link it to the current
+ // scope.
+ // NOTE: we only compile .childNodes so that
+ // we don't get into infinite loop compiling ourselves
+ $compile(element.contents())(scope);
+ }
+ );
+ };
+ });
+ })
+ .controller('GreeterController', ['$scope', function($scope) {
+ $scope.name = 'Angular';
+ $scope.html = 'Hello {{name}}';
+ }]);
+ </script>
+ <div ng-controller="GreeterController">
+ <input ng-model="name"> <br>
+ <textarea ng-model="html"></textarea> <br>
+ <div compile="html"></div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should auto compile', function() {
+ var textarea = $('textarea');
+ var output = $('div[compile]');
+ // The initial state reads 'Hello Angular'.
+ expect(output.getText()).toBe('Hello Angular');
+ textarea.clear();
+ textarea.sendKeys('{{name}}!');
+ expect(output.getText()).toBe('Angular!');
+ });
+ </file>
+ </example>
+
+ *
+ *
+ * @param {string|DOMElement} element Element or HTML string to compile into a template function.
+ * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.
+ *
+ * <div class="alert alert-error">
+ * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it
+ * e.g. will not use the right outer scope. Please pass the transclude function as a
+ * `parentBoundTranscludeFn` to the link function instead.
+ * </div>
+ *
+ * @param {number} maxPriority only apply directives lower than given priority (Only effects the
+ * root element(s), not their children)
+ * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template
+ * (a DOM element/tree) to a scope. Where:
+ *
+ * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
+ * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
+ * `template` and call the `cloneAttachFn` function allowing the caller to attach the
+ * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
+ * called as: <br> `cloneAttachFn(clonedElement, scope)` where:
+ *
+ * * `clonedElement` - is a clone of the original `element` passed into the compiler.
+ * * `scope` - is the current scope with which the linking function is working with.
+ *
+ * * `options` - An optional object hash with linking options. If `options` is provided, then the following
+ * keys may be used to control linking behavior:
+ *
+ * * `parentBoundTranscludeFn` - the transclude function made available to
+ * directives; if given, it will be passed through to the link functions of
+ * directives found in `element` during compilation.
+ * * `transcludeControllers` - an object hash with keys that map controller names
+ * to controller instances; if given, it will make the controllers
+ * available to directives.
+ * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
+ * the cloned elements; only needed for transcludes that are allowed to contain non html
+ * elements (e.g. SVG elements). See also the directive.controller property.
+ *
+ * Calling the linking function returns the element of the template. It is either the original
+ * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
+ *
+ * After linking the view is not updated until after a call to $digest which typically is done by
+ * Angular automatically.
+ *
+ * If you need access to the bound view, there are two ways to do it:
+ *
+ * - If you are not asking the linking function to clone the template, create the DOM element(s)
+ * before you send them to the compiler and keep this reference around.
+ * ```js
+ * var element = $compile('<p>{{total}}</p>')(scope);
+ * ```
+ *
+ * - if on the other hand, you need the element to be cloned, the view reference from the original
+ * example would not point to the clone, but rather to the original template that was cloned. In
+ * this case, you can access the clone via the cloneAttachFn:
+ * ```js
+ * var templateElement = angular.element('<p>{{total}}</p>'),
+ * scope = ....;
+ *
+ * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
+ * //attach the clone to DOM document at the right place
+ * });
+ *
+ * //now we have reference to the cloned DOM via `clonedElement`
+ * ```
+ *
+ *
+ * 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 provider
+ * @name $compileProvider
+ *
+ * @description
+ */
+$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
+function $CompileProvider($provide, $$sanitizeUriProvider) {
+ var hasDirectives = {},
+ Suffix = 'Directive',
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
+ CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
+ ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
+ REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
+
+ // 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)$/;
+
+ function parseIsolateBindings(scope, directiveName) {
+ var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
+
+ var bindings = {};
+
+ forEach(scope, function(definition, scopeName) {
+ var match = definition.match(LOCAL_REGEXP);
+
+ if (!match) {
+ throw $compileMinErr('iscp',
+ "Invalid isolate scope definition for directive '{0}'." +
+ " Definition: {... {1}: '{2}' ...}",
+ directiveName, scopeName, definition);
+ }
+
+ bindings[scopeName] = {
+ mode: match[1][0],
+ collection: match[2] === '*',
+ optional: match[3] === '?',
+ attrName: match[4] || scopeName
+ };
+ });
+
+ return bindings;
+ }
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#directive
+ * @kind function
+ *
+ * @description
+ * Register a new directive with the compiler.
+ *
+ * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
+ * will match as <code>ng-bind</code>), 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 || 'EA';
+ if (isObject(directive.scope)) {
+ directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);
+ }
+ directives.push(directive);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ return directives;
+ }]);
+ }
+ hasDirectives[name].push(directiveFactory);
+ } else {
+ forEach(name, reverseParams(registerDirective));
+ }
+ return this;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#aHrefSanitizationWhitelist
+ * @kind 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 preventing 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)) {
+ $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
+ return this;
+ } else {
+ return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#imgSrcSanitizationWhitelist
+ * @kind 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)) {
+ $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
+ return this;
+ } else {
+ return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#debugInfoEnabled
+ *
+ * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the
+ * current debugInfoEnabled state
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ *
+ * @kind function
+ *
+ * @description
+ * Call this method to enable/disable various debug runtime information in the compiler such as adding
+ * binding information and a reference to the current scope on to DOM elements.
+ * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
+ * * `ng-binding` CSS class
+ * * `$binding` data property containing an array of the binding expressions
+ *
+ * You may want to disable this in production for a significant performance boost. See
+ * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
+ *
+ * The default value is true.
+ */
+ var debugInfoEnabled = true;
+ this.debugInfoEnabled = function(enabled) {
+ if (isDefined(enabled)) {
+ debugInfoEnabled = enabled;
+ return this;
+ }
+ return debugInfoEnabled;
+ };
+
+ this.$get = [
+ '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
+ '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
+ function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
+ $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
+
+ var Attributes = function(element, attributesToCopy) {
+ if (attributesToCopy) {
+ var keys = Object.keys(attributesToCopy);
+ var i, l, key;
+
+ for (i = 0, l = keys.length; i < l; i++) {
+ key = keys[i];
+ this[key] = attributesToCopy[key];
+ }
+ } else {
+ this.$attr = {};
+ }
+
+ this.$$element = element;
+ };
+
+ Attributes.prototype = {
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$normalize
+ * @kind function
+ *
+ * @description
+ * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
+ * `data-`) to its normalized, camelCase form.
+ *
+ * Also there is special case for Moz prefix starting with upper case letter.
+ *
+ * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
+ *
+ * @param {string} name Name to normalize
+ */
+ $normalize: directiveNormalize,
+
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$addClass
+ * @kind 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 method
+ * @name $compile.directive.Attributes#$removeClass
+ * @kind 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);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$updateClass
+ * @kind function
+ *
+ * @description
+ * Adds and removes the appropriate CSS class values to the element based on the difference
+ * between the new and old CSS class values (specified as newClasses and oldClasses).
+ *
+ * @param {string} newClasses The current CSS className value
+ * @param {string} oldClasses The former CSS className value
+ */
+ $updateClass: function(newClasses, oldClasses) {
+ var toAdd = tokenDifference(newClasses, oldClasses);
+ if (toAdd && toAdd.length) {
+ $animate.addClass(this.$$element, toAdd);
+ }
+
+ var toRemove = tokenDifference(oldClasses, newClasses);
+ if (toRemove && toRemove.length) {
+ $animate.removeClass(this.$$element, toRemove);
+ }
+ },
+
+ /**
+ * 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) {
+ // TODO: decide whether or not to throw an error if "class"
+ //is set through this function since it may cause $updateClass to
+ //become unstable.
+
+ var node = this.$$element[0],
+ booleanKey = getBooleanAttrName(node, key),
+ aliasedKey = getAliasedAttrName(node, key),
+ observer = key,
+ nodeName;
+
+ if (booleanKey) {
+ this.$$element.prop(key, value);
+ attrName = booleanKey;
+ } else if (aliasedKey) {
+ this[aliasedKey] = value;
+ observer = aliasedKey;
+ }
+
+ 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);
+
+ if ((nodeName === 'a' && key === 'href') ||
+ (nodeName === 'img' && key === 'src')) {
+ // sanitize a[href] and img[src] values
+ this[key] = value = $$sanitizeUri(value, key === 'src');
+ } else if (nodeName === 'img' && key === 'srcset') {
+ // sanitize img[srcset] values
+ var result = "";
+
+ // first check if there are spaces because it's not the same pattern
+ var trimmedSrcset = trim(value);
+ // ( 999x ,| 999w ,| ,|, )
+ var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
+ var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
+
+ // split srcset into tuple of uri and descriptor except for the last item
+ var rawUris = trimmedSrcset.split(pattern);
+
+ // for each tuples
+ var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
+ for (var i = 0; i < nbrUrisWith2parts; i++) {
+ var innerIdx = i * 2;
+ // sanitize the uri
+ result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
+ // add the descriptor
+ result += (" " + trim(rawUris[innerIdx + 1]));
+ }
+
+ // split the last item into uri and descriptor
+ var lastTuple = trim(rawUris[i * 2]).split(/\s/);
+
+ // sanitize the last uri
+ result += $$sanitizeUri(trim(lastTuple[0]), true);
+
+ // and add the last descriptor if any
+ if (lastTuple.length === 2) {
+ result += (" " + trim(lastTuple[1]));
+ }
+ this[key] = value = result;
+ }
+
+ 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[observer], function(fn) {
+ try {
+ fn(value);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$observe
+ * @kind function
+ *
+ * @description
+ * Observes an interpolated attribute.
+ *
+ * The observer function will be invoked once during the next `$digest` following
+ * compilation. The observer is then invoked whenever the interpolated value
+ * changes.
+ *
+ * @param {string} key Normalized key. (ie ngAttribute) .
+ * @param {function(interpolatedValue)} fn Function that will be called whenever
+ the interpolated value of the attribute changes.
+ * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
+ * @returns {function()} Returns a deregistration function for this observer.
+ */
+ $observe: function(key, fn) {
+ var attrs = this,
+ $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
+ listeners = ($$observers[key] || ($$observers[key] = []));
+
+ listeners.push(fn);
+ $rootScope.$evalAsync(function() {
+ if (!listeners.$$inter && attrs.hasOwnProperty(key)) {
+ // no one registered attribute interpolation function, so lets call it manually
+ fn(attrs[key]);
+ }
+ });
+
+ return function() {
+ arrayRemove(listeners, fn);
+ };
+ }
+ };
+
+
+ function safeAddClass($element, className) {
+ try {
+ $element.addClass(className);
+ } catch (e) {
+ // ignore, since it means that we are trying to set class on
+ // SVG element, where class name is read-only.
+ }
+ }
+
+
+ var startSymbol = $interpolate.startSymbol(),
+ endSymbol = $interpolate.endSymbol(),
+ denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
+ ? identity
+ : function denormalizeTemplate(template) {
+ return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
+ },
+ NG_ATTR_BINDING = /^ngAttr[A-Z]/;
+
+ compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
+ var bindings = $element.data('$binding') || [];
+
+ if (isArray(binding)) {
+ bindings = bindings.concat(binding);
+ } else {
+ bindings.push(binding);
+ }
+
+ $element.data('$binding', bindings);
+ } : noop;
+
+ compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {
+ safeAddClass($element, 'ng-binding');
+ } : noop;
+
+ compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {
+ var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';
+ $element.data(dataName, scope);
+ } : noop;
+
+ compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {
+ safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');
+ } : noop;
+
+ return compile;
+
+ //================================
+
+ function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
+ previousCompileContext) {
+ if (!($compileNodes instanceof jqLite)) {
+ // jquery always rewraps, whereas we need to preserve the original selector so that we can
+ // modify it.
+ $compileNodes = jqLite($compileNodes);
+ }
+ // We can not compile top level text elements since text nodes can be merged and we will
+ // not be able to attach scope data to them, so we will wrap them in <span>
+ forEach($compileNodes, function(node, index) {
+ if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
+ $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
+ }
+ });
+ var compositeLinkFn =
+ compileNodes($compileNodes, transcludeFn, $compileNodes,
+ maxPriority, ignoreDirective, previousCompileContext);
+ compile.$$addScopeClass($compileNodes);
+ var namespace = null;
+ return function publicLinkFn(scope, cloneConnectFn, options) {
+ assertArg(scope, 'scope');
+
+ options = options || {};
+ var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
+ transcludeControllers = options.transcludeControllers,
+ futureParentElement = options.futureParentElement;
+
+ // When `parentBoundTranscludeFn` is passed, it is a
+ // `controllersBoundTransclude` function (it was previously passed
+ // as `transclude` to directive.link) so we must unwrap it to get
+ // its `boundTranscludeFn`
+ if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {
+ parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;
+ }
+
+ if (!namespace) {
+ namespace = detectNamespaceForChildElements(futureParentElement);
+ }
+ var $linkNode;
+ if (namespace !== 'html') {
+ // When using a directive with replace:true and templateUrl the $compileNodes
+ // (or a child element inside of them)
+ // might change, so we need to recreate the namespace adapted compileNodes
+ // for call to the link function.
+ // Note: This will already clone the nodes...
+ $linkNode = jqLite(
+ wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
+ );
+ } else if (cloneConnectFn) {
+ // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
+ // and sometimes changes the structure of the DOM.
+ $linkNode = JQLitePrototype.clone.call($compileNodes);
+ } else {
+ $linkNode = $compileNodes;
+ }
+
+ if (transcludeControllers) {
+ for (var controllerName in transcludeControllers) {
+ $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);
+ }
+ }
+
+ compile.$$addScopeInfo($linkNode, scope);
+
+ if (cloneConnectFn) cloneConnectFn($linkNode, scope);
+ if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
+ return $linkNode;
+ };
+ }
+
+ function detectNamespaceForChildElements(parentElement) {
+ // TODO: Make this detect MathML as well...
+ var node = parentElement && parentElement[0];
+ if (!node) {
+ return 'html';
+ } else {
+ return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
+ }
+ }
+
+ /**
+ * Compile function matches each node in nodeList against the directives. Once all directives
+ * for a particular node are collected their compile functions are executed. The compile
+ * functions return values - the linking functions - are combined into a composite linking
+ * function, which is the a linking function for the node.
+ *
+ * @param {NodeList} nodeList an array of nodes or NodeList to compile
+ * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
+ * scope argument is auto-generated to the new child of the transcluded parent scope.
+ * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
+ * the rootElement must be set the jqLite collection of the compile root. This is
+ * needed so that the jqLite collection items can be replaced with widgets.
+ * @param {number=} maxPriority Max directive priority.
+ * @returns {Function} A composite linking function of all of the matched directives or null.
+ */
+ function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
+ previousCompileContext) {
+ var linkFns = [],
+ attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;
+
+ for (var i = 0; i < nodeList.length; i++) {
+ attrs = new Attributes();
+
+ // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
+ directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
+ ignoreDirective);
+
+ nodeLinkFn = (directives.length)
+ ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
+ null, [], [], previousCompileContext)
+ : null;
+
+ if (nodeLinkFn && nodeLinkFn.scope) {
+ compile.$$addScopeClass(attrs.$$element);
+ }
+
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
+ !(childNodes = nodeList[i].childNodes) ||
+ !childNodes.length)
+ ? null
+ : compileNodes(childNodes,
+ nodeLinkFn ? (
+ (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
+ && nodeLinkFn.transclude) : transcludeFn);
+
+ if (nodeLinkFn || childLinkFn) {
+ linkFns.push(i, nodeLinkFn, childLinkFn);
+ linkFnFound = true;
+ nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
+ }
+
+ //use the previous context only for the first element in the virtual group
+ previousCompileContext = null;
+ }
+
+ // return a linking function if we have found anything, null otherwise
+ return linkFnFound ? compositeLinkFn : null;
+
+ function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
+ var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
+ var stableNodeList;
+
+
+ if (nodeLinkFnFound) {
+ // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our
+ // offsets don't get screwed up
+ var nodeListLength = nodeList.length;
+ stableNodeList = new Array(nodeListLength);
+
+ // create a sparse array by only copying the elements which have a linkFn
+ for (i = 0; i < linkFns.length; i+=3) {
+ idx = linkFns[i];
+ stableNodeList[idx] = nodeList[idx];
+ }
+ } else {
+ stableNodeList = nodeList;
+ }
+
+ for (i = 0, ii = linkFns.length; i < ii;) {
+ node = stableNodeList[linkFns[i++]];
+ nodeLinkFn = linkFns[i++];
+ childLinkFn = linkFns[i++];
+
+ if (nodeLinkFn) {
+ if (nodeLinkFn.scope) {
+ childScope = scope.$new();
+ compile.$$addScopeInfo(jqLite(node), childScope);
+ } else {
+ childScope = scope;
+ }
+
+ if (nodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(
+ scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
+ nodeLinkFn.elementTranscludeOnThisElement);
+
+ } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
+ childBoundTranscludeFn = parentBoundTranscludeFn;
+
+ } else if (!parentBoundTranscludeFn && transcludeFn) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
+
+ } else {
+ childBoundTranscludeFn = null;
+ }
+
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
+
+ } else if (childLinkFn) {
+ childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
+ }
+ }
+ }
+ }
+
+ function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {
+
+ var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
+
+ if (!transcludedScope) {
+ transcludedScope = scope.$new(false, containingScope);
+ transcludedScope.$$transcluded = true;
+ }
+
+ return transcludeFn(transcludedScope, cloneFn, {
+ parentBoundTranscludeFn: previousBoundTranscludeFn,
+ transcludeControllers: controllers,
+ futureParentElement: futureParentElement
+ });
+ };
+
+ return boundTranscludeFn;
+ }
+
+ /**
+ * Looks for directives on the given node and adds them to the directive collection which is
+ * sorted.
+ *
+ * @param node Node to search.
+ * @param directives An array to which the directives are added to. This array is sorted before
+ * the function returns.
+ * @param attrs The shared attrs object which is used to populate the normalized attributes.
+ * @param {number=} maxPriority Max directive priority.
+ */
+ function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
+ var nodeType = node.nodeType,
+ attrsMap = attrs.$attr,
+ match,
+ className;
+
+ switch (nodeType) {
+ case NODE_TYPE_ELEMENT: /* Element */
+ // use the node name: <directive>
+ addDirective(directives,
+ directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
+
+ // iterate over the attributes
+ for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
+ j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
+ var attrStartName = false;
+ var attrEndName = false;
+
+ attr = nAttrs[j];
+ name = attr.name;
+ value = trim(attr.value);
+
+ // support ngAttr attribute binding
+ ngAttrName = directiveNormalize(name);
+ if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
+ name = name.replace(PREFIX_REGEXP, '')
+ .substr(8).replace(/_(.)/g, function(match, letter) {
+ return letter.toUpperCase();
+ });
+ }
+
+ var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
+ if (directiveIsMultiElement(directiveNName)) {
+ if (ngAttrName === directiveNName + 'Start') {
+ attrStartName = name;
+ attrEndName = name.substr(0, name.length - 5) + 'end';
+ name = name.substr(0, name.length - 6);
+ }
+ }
+
+ nName = directiveNormalize(name.toLowerCase());
+ attrsMap[nName] = name;
+ if (isNgAttr || !attrs.hasOwnProperty(nName)) {
+ attrs[nName] = value;
+ if (getBooleanAttrName(node, nName)) {
+ attrs[nName] = true; // presence means true
+ }
+ }
+ addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
+ addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
+ attrEndName);
+ }
+
+ // use class as directive
+ className = node.className;
+ if (isObject(className)) {
+ // Maybe SVGAnimatedString
+ className = className.animVal;
+ }
+ if (isString(className) && className !== '') {
+ while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
+ nName = directiveNormalize(match[2]);
+ if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
+ attrs[nName] = trim(match[3]);
+ }
+ className = className.substr(match.index + match[0].length);
+ }
+ }
+ break;
+ case NODE_TYPE_TEXT: /* Text Node */
+ addTextInterpolateDirective(directives, node.nodeValue);
+ break;
+ case NODE_TYPE_COMMENT: /* Comment */
+ try {
+ match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
+ if (match) {
+ nName = directiveNormalize(match[1]);
+ if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
+ attrs[nName] = trim(match[2]);
+ }
+ }
+ } catch (e) {
+ // turns out that under some circumstances IE9 throws errors when one attempts to read
+ // comment's node value.
+ // Just ignore it and continue. (Can't seem to reproduce in test case.)
+ }
+ break;
+ }
+
+ directives.sort(byPriority);
+ return directives;
+ }
+
+ /**
+ * Given a node with an directive-start it collects all of the siblings until it finds
+ * directive-end.
+ * @param node
+ * @param attrStart
+ * @param attrEnd
+ * @returns {*}
+ */
+ function groupScan(node, attrStart, attrEnd) {
+ var nodes = [];
+ var depth = 0;
+ if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
+ do {
+ if (!node) {
+ throw $compileMinErr('uterdir',
+ "Unterminated attribute, found '{0}' but no matching '{1}' found.",
+ attrStart, attrEnd);
+ }
+ if (node.nodeType == NODE_TYPE_ELEMENT) {
+ if (node.hasAttribute(attrStart)) depth++;
+ if (node.hasAttribute(attrEnd)) depth--;
+ }
+ nodes.push(node);
+ node = node.nextSibling;
+ } while (depth > 0);
+ } else {
+ nodes.push(node);
+ }
+
+ return jqLite(nodes);
+ }
+
+ /**
+ * Wrapper for linking function which converts normal linking function into a grouped
+ * linking function.
+ * @param linkFn
+ * @param attrStart
+ * @param attrEnd
+ * @returns {Function}
+ */
+ function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
+ return function(scope, element, attrs, controllers, transcludeFn) {
+ element = groupScan(element[0], attrStart, attrEnd);
+ return linkFn(scope, element, attrs, controllers, transcludeFn);
+ };
+ }
+
+ /**
+ * Once the directives have been collected, their compile functions are executed. This method
+ * is responsible for inlining directive templates as well as terminating the application
+ * of the directives if the terminal directive has been reached.
+ *
+ * @param {Array} directives Array of collected directives to execute their compile function.
+ * this needs to be pre-sorted by priority order.
+ * @param {Node} compileNode The raw DOM node to apply the compile functions to
+ * @param {Object} templateAttrs The shared attribute function
+ * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
+ * scope argument is auto-generated to the new
+ * child of the transcluded parent scope.
+ * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
+ * argument has the root jqLite array so that we can replace nodes
+ * on it.
+ * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
+ * compiling the transclusion.
+ * @param {Array.<Function>} preLinkFns
+ * @param {Array.<Function>} postLinkFns
+ * @param {Object} previousCompileContext Context used for previous compilation of the current
+ * node
+ * @returns {Function} linkFn
+ */
+ function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
+ jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
+ previousCompileContext) {
+ previousCompileContext = previousCompileContext || {};
+
+ var terminalPriority = -Number.MAX_VALUE,
+ newScopeDirective,
+ controllerDirectives = previousCompileContext.controllerDirectives,
+ controllers,
+ newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
+ templateDirective = previousCompileContext.templateDirective,
+ nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
+ hasTranscludeDirective = false,
+ hasTemplate = false,
+ hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
+ $compileNode = templateAttrs.$$element = jqLite(compileNode),
+ directive,
+ directiveName,
+ $template,
+ replaceDirective = originalReplaceDirective,
+ childTranscludeFn = transcludeFn,
+ linkFn,
+ directiveValue;
+
+ // executes all directives on the current element
+ for (var i = 0, ii = directives.length; i < ii; i++) {
+ directive = directives[i];
+ var attrStart = directive.$$start;
+ var attrEnd = directive.$$end;
+
+ // collect multiblock sections
+ if (attrStart) {
+ $compileNode = groupScan(compileNode, attrStart, attrEnd);
+ }
+ $template = undefined;
+
+ if (terminalPriority > directive.priority) {
+ break; // prevent further processing of directives
+ }
+
+ if (directiveValue = directive.scope) {
+
+ // skip the check for directives with async templates, we'll check the derived sync
+ // directive when the template arrives
+ if (!directive.templateUrl) {
+ if (isObject(directiveValue)) {
+ // This directive is trying to add an isolated scope.
+ // Check that there is no scope of any kind already
+ assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,
+ directive, $compileNode);
+ newIsolateScopeDirective = directive;
+ } else {
+ // This directive is trying to add a child scope.
+ // Check that there is no isolated scope already
+ assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
+ $compileNode);
+ }
+ }
+
+ newScopeDirective = newScopeDirective || directive;
+ }
+
+ directiveName = directive.name;
+
+ if (!directive.templateUrl && directive.controller) {
+ directiveValue = directive.controller;
+ controllerDirectives = controllerDirectives || {};
+ assertNoDuplicate("'" + directiveName + "' controller",
+ controllerDirectives[directiveName], directive, $compileNode);
+ controllerDirectives[directiveName] = directive;
+ }
+
+ if (directiveValue = directive.transclude) {
+ hasTranscludeDirective = true;
+
+ // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
+ // This option should only be used by directives that know how to safely handle element transclusion,
+ // where the transcluded nodes are added or replaced after linking.
+ if (!directive.$$tlb) {
+ assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
+ nonTlbTranscludeDirective = directive;
+ }
+
+ if (directiveValue == 'element') {
+ hasElementTranscludeDirective = true;
+ terminalPriority = directive.priority;
+ $template = $compileNode;
+ $compileNode = templateAttrs.$$element =
+ jqLite(document.createComment(' ' + directiveName + ': ' +
+ templateAttrs[directiveName] + ' '));
+ compileNode = $compileNode[0];
+ replaceWith(jqCollection, sliceArgs($template), compileNode);
+
+ childTranscludeFn = compile($template, transcludeFn, terminalPriority,
+ replaceDirective && replaceDirective.name, {
+ // Don't pass in:
+ // - controllerDirectives - otherwise we'll create duplicates controllers
+ // - newIsolateScopeDirective or templateDirective - combining templates with
+ // element transclusion doesn't make sense.
+ //
+ // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
+ // on the same element more than once.
+ nonTlbTranscludeDirective: nonTlbTranscludeDirective
+ });
+ } else {
+ $template = jqLite(jqLiteClone(compileNode)).contents();
+ $compileNode.empty(); // clear contents
+ childTranscludeFn = compile($template, transcludeFn);
+ }
+ }
+
+ if (directive.template) {
+ hasTemplate = true;
+ assertNoDuplicate('template', templateDirective, directive, $compileNode);
+ templateDirective = directive;
+
+ directiveValue = (isFunction(directive.template))
+ ? directive.template($compileNode, templateAttrs)
+ : directive.template;
+
+ directiveValue = denormalizeTemplate(directiveValue);
+
+ if (directive.replace) {
+ replaceDirective = directive;
+ if (jqLiteIsTextNode(directiveValue)) {
+ $template = [];
+ } else {
+ $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));
+ }
+ compileNode = $template[0];
+
+ if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
+ throw $compileMinErr('tplrt',
+ "Template for directive '{0}' must have exactly one root element. {1}",
+ directiveName, '');
+ }
+
+ replaceWith(jqCollection, $compileNode, compileNode);
+
+ var newTemplateAttrs = {$attr: {}};
+
+ // combine directives from the original node and from the template:
+ // - take the array of directives for this element
+ // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
+ // - collect directives from the template and sort them by priority
+ // - combine directives as: processed + template + unprocessed
+ var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
+ var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
+
+ if (newIsolateScopeDirective) {
+ markDirectivesAsIsolate(templateDirectives);
+ }
+ directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
+ mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
+
+ ii = directives.length;
+ } else {
+ $compileNode.html(directiveValue);
+ }
+ }
+
+ if (directive.templateUrl) {
+ hasTemplate = true;
+ assertNoDuplicate('template', templateDirective, directive, $compileNode);
+ templateDirective = directive;
+
+ if (directive.replace) {
+ replaceDirective = directive;
+ }
+
+ nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
+ templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
+ controllerDirectives: controllerDirectives,
+ newIsolateScopeDirective: newIsolateScopeDirective,
+ templateDirective: templateDirective,
+ nonTlbTranscludeDirective: nonTlbTranscludeDirective
+ });
+ ii = directives.length;
+ } else if (directive.compile) {
+ try {
+ linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
+ if (isFunction(linkFn)) {
+ addLinkFns(null, linkFn, attrStart, attrEnd);
+ } else if (linkFn) {
+ addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
+ }
+ } catch (e) {
+ $exceptionHandler(e, startingTag($compileNode));
+ }
+ }
+
+ if (directive.terminal) {
+ nodeLinkFn.terminal = true;
+ terminalPriority = Math.max(terminalPriority, directive.priority);
+ }
+
+ }
+
+ nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
+ nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
+ nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;
+ nodeLinkFn.templateOnThisElement = hasTemplate;
+ nodeLinkFn.transclude = childTranscludeFn;
+
+ previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
+
+ // might be normal or delayed nodeLinkFn depending on if templateUrl is present
+ return nodeLinkFn;
+
+ ////////////////////
+
+ function addLinkFns(pre, post, attrStart, attrEnd) {
+ if (pre) {
+ if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
+ pre.require = directive.require;
+ pre.directiveName = directiveName;
+ if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
+ pre = cloneAndAnnotateFn(pre, {isolateScope: true});
+ }
+ preLinkFns.push(pre);
+ }
+ if (post) {
+ if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
+ post.require = directive.require;
+ post.directiveName = directiveName;
+ if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
+ post = cloneAndAnnotateFn(post, {isolateScope: true});
+ }
+ postLinkFns.push(post);
+ }
+ }
+
+
+ function getControllers(directiveName, require, $element, elementControllers) {
+ var value, retrievalMethod = 'data', optional = false;
+ var $searchElement = $element;
+ var match;
+ if (isString(require)) {
+ match = require.match(REQUIRE_PREFIX_REGEXP);
+ require = require.substring(match[0].length);
+
+ if (match[3]) {
+ if (match[1]) match[3] = null;
+ else match[1] = match[3];
+ }
+ if (match[1] === '^') {
+ retrievalMethod = 'inheritedData';
+ } else if (match[1] === '^^') {
+ retrievalMethod = 'inheritedData';
+ $searchElement = $element.parent();
+ }
+ if (match[2] === '?') {
+ optional = true;
+ }
+
+ value = null;
+
+ if (elementControllers && retrievalMethod === 'data') {
+ if (value = elementControllers[require]) {
+ value = value.instance;
+ }
+ }
+ value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');
+
+ if (!value && !optional) {
+ throw $compileMinErr('ctreq',
+ "Controller '{0}', required by directive '{1}', can't be found!",
+ require, directiveName);
+ }
+ return value || null;
+ } else if (isArray(require)) {
+ value = [];
+ forEach(require, function(require) {
+ value.push(getControllers(directiveName, require, $element, elementControllers));
+ });
+ }
+ return value;
+ }
+
+
+ function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
+ var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,
+ attrs;
+
+ if (compileNode === linkNode) {
+ attrs = templateAttrs;
+ $element = templateAttrs.$$element;
+ } else {
+ $element = jqLite(linkNode);
+ attrs = new Attributes($element, templateAttrs);
+ }
+
+ if (newIsolateScopeDirective) {
+ isolateScope = scope.$new(true);
+ }
+
+ if (boundTranscludeFn) {
+ // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
+ // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
+ transcludeFn = controllersBoundTransclude;
+ transcludeFn.$$boundTransclude = boundTranscludeFn;
+ }
+
+ if (controllerDirectives) {
+ // TODO: merge `controllers` and `elementControllers` into single object.
+ controllers = {};
+ elementControllers = {};
+ forEach(controllerDirectives, function(directive) {
+ var locals = {
+ $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
+ $element: $element,
+ $attrs: attrs,
+ $transclude: transcludeFn
+ }, controllerInstance;
+
+ controller = directive.controller;
+ if (controller == '@') {
+ controller = attrs[directive.name];
+ }
+
+ controllerInstance = $controller(controller, locals, true, directive.controllerAs);
+
+ // For directives with element transclusion the element is a comment,
+ // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
+ // clean up (http://bugs.jquery.com/ticket/8335).
+ // Instead, we save the controllers for the element in a local hash and attach to .data
+ // later, once we have the actual element.
+ elementControllers[directive.name] = controllerInstance;
+ if (!hasElementTranscludeDirective) {
+ $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
+ }
+
+ controllers[directive.name] = controllerInstance;
+ });
+ }
+
+ if (newIsolateScopeDirective) {
+ compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
+ templateDirective === newIsolateScopeDirective.$$originalDirective)));
+ compile.$$addScopeClass($element, true);
+
+ var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];
+ var isolateBindingContext = isolateScope;
+ if (isolateScopeController && isolateScopeController.identifier &&
+ newIsolateScopeDirective.bindToController === true) {
+ isolateBindingContext = isolateScopeController.instance;
+ }
+
+ forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {
+ var attrName = definition.attrName,
+ optional = definition.optional,
+ mode = definition.mode, // @, =, or &
+ lastValue,
+ parentGet, parentSet, compare;
+
+ switch (mode) {
+
+ case '@':
+ attrs.$observe(attrName, function(value) {
+ isolateBindingContext[scopeName] = value;
+ });
+ attrs.$$observers[attrName].$$scope = scope;
+ if (attrs[attrName]) {
+ // If the attribute has been provided then we trigger an interpolation to ensure
+ // the value is there for use in the link fn
+ isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);
+ }
+ break;
+
+ case '=':
+ if (optional && !attrs[attrName]) {
+ return;
+ }
+ parentGet = $parse(attrs[attrName]);
+ if (parentGet.literal) {
+ compare = equals;
+ } else {
+ compare = function(a, b) { return a === b || (a !== a && b !== b); };
+ }
+ parentSet = parentGet.assign || function() {
+ // reset the change, or we will throw this exception on every $digest
+ lastValue = isolateBindingContext[scopeName] = parentGet(scope);
+ throw $compileMinErr('nonassign',
+ "Expression '{0}' used with directive '{1}' is non-assignable!",
+ attrs[attrName], newIsolateScopeDirective.name);
+ };
+ lastValue = isolateBindingContext[scopeName] = parentGet(scope);
+ var parentValueWatch = function parentValueWatch(parentValue) {
+ if (!compare(parentValue, isolateBindingContext[scopeName])) {
+ // we are out of sync and need to copy
+ if (!compare(parentValue, lastValue)) {
+ // parent changed and it has precedence
+ isolateBindingContext[scopeName] = parentValue;
+ } else {
+ // if the parent can be assigned then do so
+ parentSet(scope, parentValue = isolateBindingContext[scopeName]);
+ }
+ }
+ return lastValue = parentValue;
+ };
+ parentValueWatch.$stateful = true;
+ var unwatch;
+ if (definition.collection) {
+ unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
+ } else {
+ unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
+ }
+ isolateScope.$on('$destroy', unwatch);
+ break;
+
+ case '&':
+ parentGet = $parse(attrs[attrName]);
+ isolateBindingContext[scopeName] = function(locals) {
+ return parentGet(scope, locals);
+ };
+ break;
+ }
+ });
+ }
+ if (controllers) {
+ forEach(controllers, function(controller) {
+ controller();
+ });
+ controllers = null;
+ }
+
+ // PRELINKING
+ for (i = 0, ii = preLinkFns.length; i < ii; i++) {
+ linkFn = preLinkFns[i];
+ invokeLinkFn(linkFn,
+ linkFn.isolateScope ? isolateScope : scope,
+ $element,
+ attrs,
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
+ transcludeFn
+ );
+ }
+
+ // RECURSION
+ // We only pass the isolate scope, if the isolate directive has a template,
+ // otherwise the child elements do not belong to the isolate directive.
+ var scopeToChild = scope;
+ if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
+ scopeToChild = isolateScope;
+ }
+ childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
+
+ // POSTLINKING
+ for (i = postLinkFns.length - 1; i >= 0; i--) {
+ linkFn = postLinkFns[i];
+ invokeLinkFn(linkFn,
+ linkFn.isolateScope ? isolateScope : scope,
+ $element,
+ attrs,
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
+ transcludeFn
+ );
+ }
+
+ // This is the function that is injected as `$transclude`.
+ // Note: all arguments are optional!
+ function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
+ var transcludeControllers;
+
+ // No scope passed in:
+ if (!isScope(scope)) {
+ futureParentElement = cloneAttachFn;
+ cloneAttachFn = scope;
+ scope = undefined;
+ }
+
+ if (hasElementTranscludeDirective) {
+ transcludeControllers = elementControllers;
+ }
+ if (!futureParentElement) {
+ futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
+ }
+ return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
+ }
+ }
+ }
+
+ function markDirectivesAsIsolate(directives) {
+ // mark all directives as needing isolate scope.
+ for (var j = 0, jj = directives.length; j < jj; j++) {
+ directives[j] = inherit(directives[j], {$$isolateScope: true});
+ }
+ }
+
+ /**
+ * looks up the directive and decorates it with exception handling and proper parameters. We
+ * call this the boundDirective.
+ *
+ * @param {string} name name of the directive to look up.
+ * @param {string} location The directive must be found in specific format.
+ * String containing any of theses characters:
+ *
+ * * `E`: element name
+ * * `A': attribute
+ * * `C`: class
+ * * `M`: comment
+ * @returns {boolean} true if directive was added.
+ */
+ function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
+ endAttrName) {
+ if (name === ignoreDirective) return null;
+ var match = null;
+ if (hasDirectives.hasOwnProperty(name)) {
+ for (var directive, directives = $injector.get(name + Suffix),
+ i = 0, ii = directives.length; i < ii; i++) {
+ try {
+ directive = directives[i];
+ if ((maxPriority === undefined || maxPriority > directive.priority) &&
+ directive.restrict.indexOf(location) != -1) {
+ if (startAttrName) {
+ directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
+ }
+ tDirectives.push(directive);
+ match = directive;
+ }
+ } catch (e) { $exceptionHandler(e); }
+ }
+ }
+ return match;
+ }
+
+
+ /**
+ * looks up the directive and returns true if it is a multi-element directive,
+ * and therefore requires DOM nodes between -start and -end markers to be grouped
+ * together.
+ *
+ * @param {string} name name of the directive to look up.
+ * @returns true if directive was registered as multi-element.
+ */
+ function directiveIsMultiElement(name) {
+ if (hasDirectives.hasOwnProperty(name)) {
+ for (var directive, directives = $injector.get(name + Suffix),
+ i = 0, ii = directives.length; i < ii; i++) {
+ directive = directives[i];
+ if (directive.multiElement) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * When the element is replaced with HTML template then the new attributes
+ * on the template need to be merged with the existing attributes in the DOM.
+ * The desired effect is to have both of the attributes present.
+ *
+ * @param {object} dst destination attributes (original DOM)
+ * @param {object} src source attributes (from the directive template)
+ */
+ function mergeTemplateAttributes(dst, src) {
+ var srcAttr = src.$attr,
+ dstAttr = dst.$attr,
+ $element = dst.$$element;
+
+ // reapply the old attributes to the new element
+ forEach(dst, function(value, key) {
+ if (key.charAt(0) != '$') {
+ if (src[key] && src[key] !== value) {
+ value += (key === 'style' ? ';' : ' ') + src[key];
+ }
+ dst.$set(key, value, true, srcAttr[key]);
+ }
+ });
+
+ // copy the new attributes on the old attrs object
+ forEach(src, function(value, key) {
+ if (key == 'class') {
+ safeAddClass($element, value);
+ dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
+ } else if (key == 'style') {
+ $element.attr('style', $element.attr('style') + ';' + value);
+ dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
+ // `dst` will never contain hasOwnProperty as DOM parser won't let it.
+ // You will get an "InvalidCharacterError: DOM Exception 5" error if you
+ // have an attribute like "has-own-property" or "data-has-own-property", etc.
+ } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
+ dst[key] = value;
+ dstAttr[key] = srcAttr[key];
+ }
+ });
+ }
+
+
+ function compileTemplateUrl(directives, $compileNode, tAttrs,
+ $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
+ var linkQueue = [],
+ afterTemplateNodeLinkFn,
+ afterTemplateChildLinkFn,
+ beforeTemplateCompileNode = $compileNode[0],
+ origAsyncDirective = directives.shift(),
+ derivedSyncDirective = inherit(origAsyncDirective, {
+ templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
+ }),
+ templateUrl = (isFunction(origAsyncDirective.templateUrl))
+ ? origAsyncDirective.templateUrl($compileNode, tAttrs)
+ : origAsyncDirective.templateUrl,
+ templateNamespace = origAsyncDirective.templateNamespace;
+
+ $compileNode.empty();
+
+ $templateRequest(templateUrl)
+ .then(function(content) {
+ var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
+
+ content = denormalizeTemplate(content);
+
+ if (origAsyncDirective.replace) {
+ if (jqLiteIsTextNode(content)) {
+ $template = [];
+ } else {
+ $template = removeComments(wrapTemplate(templateNamespace, trim(content)));
+ }
+ compileNode = $template[0];
+
+ if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
+ throw $compileMinErr('tplrt',
+ "Template for directive '{0}' must have exactly one root element. {1}",
+ origAsyncDirective.name, templateUrl);
+ }
+
+ tempTemplateAttrs = {$attr: {}};
+ replaceWith($rootElement, $compileNode, compileNode);
+ var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
+
+ if (isObject(origAsyncDirective.scope)) {
+ markDirectivesAsIsolate(templateDirectives);
+ }
+ directives = templateDirectives.concat(directives);
+ mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
+ } else {
+ compileNode = beforeTemplateCompileNode;
+ $compileNode.html(content);
+ }
+
+ directives.unshift(derivedSyncDirective);
+
+ afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
+ childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
+ previousCompileContext);
+ forEach($rootElement, function(node, i) {
+ if (node == compileNode) {
+ $rootElement[i] = $compileNode[0];
+ }
+ });
+ afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
+
+ while (linkQueue.length) {
+ var scope = linkQueue.shift(),
+ beforeTemplateLinkNode = linkQueue.shift(),
+ linkRootElement = linkQueue.shift(),
+ boundTranscludeFn = linkQueue.shift(),
+ linkNode = $compileNode[0];
+
+ if (scope.$$destroyed) continue;
+
+ if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
+ var oldClasses = beforeTemplateLinkNode.className;
+
+ if (!(previousCompileContext.hasElementTranscludeDirective &&
+ origAsyncDirective.replace)) {
+ // it was cloned therefore we have to clone as well.
+ linkNode = jqLiteClone(compileNode);
+ }
+ replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
+
+ // Copy in CSS classes from original node
+ safeAddClass(jqLite(linkNode), oldClasses);
+ }
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
+ } else {
+ childBoundTranscludeFn = boundTranscludeFn;
+ }
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
+ childBoundTranscludeFn);
+ }
+ linkQueue = null;
+ });
+
+ return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
+ var childBoundTranscludeFn = boundTranscludeFn;
+ if (scope.$$destroyed) return;
+ if (linkQueue) {
+ linkQueue.push(scope,
+ node,
+ rootElement,
+ childBoundTranscludeFn);
+ } else {
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
+ }
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
+ }
+ };
+ }
+
+
+ /**
+ * Sorting function for bound directives.
+ */
+ function byPriority(a, b) {
+ var diff = b.priority - a.priority;
+ if (diff !== 0) return diff;
+ if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
+ return a.index - b.index;
+ }
+
+
+ function assertNoDuplicate(what, previousDirective, directive, element) {
+ if (previousDirective) {
+ throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
+ previousDirective.name, directive.name, what, startingTag(element));
+ }
+ }
+
+
+ function addTextInterpolateDirective(directives, text) {
+ var interpolateFn = $interpolate(text, true);
+ if (interpolateFn) {
+ directives.push({
+ priority: 0,
+ compile: function textInterpolateCompileFn(templateNode) {
+ var templateNodeParent = templateNode.parent(),
+ hasCompileParent = !!templateNodeParent.length;
+
+ // When transcluding a template that has bindings in the root
+ // we don't have a parent and thus need to add the class during linking fn.
+ if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);
+
+ return function textInterpolateLinkFn(scope, node) {
+ var parent = node.parent();
+ if (!hasCompileParent) compile.$$addBindingClass(parent);
+ compile.$$addBindingInfo(parent, interpolateFn.expressions);
+ scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
+ node[0].nodeValue = value;
+ });
+ };
+ }
+ });
+ }
+ }
+
+
+ function wrapTemplate(type, template) {
+ type = lowercase(type || 'html');
+ switch (type) {
+ case 'svg':
+ case 'math':
+ var wrapper = document.createElement('div');
+ wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
+ return wrapper.childNodes[0].childNodes;
+ default:
+ return template;
+ }
+ }
+
+
+ function getTrustedContext(node, attrNormalizedName) {
+ if (attrNormalizedName == "srcdoc") {
+ return $sce.HTML;
+ }
+ var tag = nodeName_(node);
+ // maction[xlink:href] can source SVG. It's not limited to <maction>.
+ if (attrNormalizedName == "xlinkHref" ||
+ (tag == "form" && attrNormalizedName == "action") ||
+ (tag != "img" && (attrNormalizedName == "src" ||
+ attrNormalizedName == "ngSrc"))) {
+ return $sce.RESOURCE_URL;
+ }
+ }
+
+
+ function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
+ var trustedContext = getTrustedContext(node, name);
+ allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
+
+ var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
+
+ // no interpolation found -> ignore
+ if (!interpolateFn) return;
+
+
+ if (name === "multiple" && nodeName_(node) === "select") {
+ throw $compileMinErr("selmulti",
+ "Binding to the 'multiple' attribute is not supported. Element: {0}",
+ startingTag(node));
+ }
+
+ directives.push({
+ priority: 100,
+ compile: function() {
+ return {
+ pre: function attrInterpolatePreLinkFn(scope, element, attr) {
+ var $$observers = (attr.$$observers || (attr.$$observers = {}));
+
+ if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
+ throw $compileMinErr('nodomevents',
+ "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
+ "ng- versions (such as ng-click instead of onclick) instead.");
+ }
+
+ // If the attribute has changed since last $interpolate()ed
+ var newValue = attr[name];
+ if (newValue !== value) {
+ // we need to interpolate again since the attribute value has been updated
+ // (e.g. by another directive's compile function)
+ // ensure unset/empty values make interpolateFn falsy
+ interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
+ value = newValue;
+ }
+
+ // if attribute was updated so that there is no interpolation going on we don't want to
+ // register any observers
+ if (!interpolateFn) return;
+
+ // initialize attr object so that it's ready in case we need the value for isolate
+ // scope initialization, otherwise the value would not be available from isolate
+ // directive's linking fn during linking phase
+ attr[name] = interpolateFn(scope);
+
+ ($$observers[name] || ($$observers[name] = [])).$$inter = true;
+ (attr.$$observers && attr.$$observers[name].$$scope || scope).
+ $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
+ //special case for class attribute addition + removal
+ //so that class changes can tap into the animation
+ //hooks provided by the $animate service. Be sure to
+ //skip animations when the first digest occurs (when
+ //both the new and the old values are the same) since
+ //the CSS classes are the non-interpolated values
+ if (name === 'class' && newValue != oldValue) {
+ attr.$updateClass(newValue, oldValue);
+ } else {
+ attr.$set(name, newValue);
+ }
+ });
+ }
+ };
+ }
+ });
+ }
+
+
+ /**
+ * This is a special jqLite.replaceWith, which can replace items which
+ * have no parents, provided that the containing jqLite collection is provided.
+ *
+ * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
+ * in the root of the tree.
+ * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
+ * the shell, but replace its DOM node reference.
+ * @param {Node} newNode The new DOM node.
+ */
+ function replaceWith($rootElement, elementsToRemove, newNode) {
+ var firstElementToRemove = elementsToRemove[0],
+ removeCount = elementsToRemove.length,
+ parent = firstElementToRemove.parentNode,
+ i, ii;
+
+ if ($rootElement) {
+ for (i = 0, ii = $rootElement.length; i < ii; i++) {
+ if ($rootElement[i] == firstElementToRemove) {
+ $rootElement[i++] = newNode;
+ for (var j = i, j2 = j + removeCount - 1,
+ jj = $rootElement.length;
+ j < jj; j++, j2++) {
+ if (j2 < jj) {
+ $rootElement[j] = $rootElement[j2];
+ } else {
+ delete $rootElement[j];
+ }
+ }
+ $rootElement.length -= removeCount - 1;
+
+ // If the replaced element is also the jQuery .context then replace it
+ // .context is a deprecated jQuery api, so we should set it only when jQuery set it
+ // http://api.jquery.com/context/
+ if ($rootElement.context === firstElementToRemove) {
+ $rootElement.context = newNode;
+ }
+ break;
+ }
+ }
+ }
+
+ if (parent) {
+ parent.replaceChild(newNode, firstElementToRemove);
+ }
+
+ // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(firstElementToRemove);
+
+ // Copy over user data (that includes Angular's $scope etc.). Don't copy private
+ // data here because there's no public interface in jQuery to do that and copying over
+ // event listeners (which is the main use of private data) wouldn't work anyway.
+ jqLite(newNode).data(jqLite(firstElementToRemove).data());
+
+ // Remove data of the replaced element. We cannot just call .remove()
+ // on the element it since that would deallocate scope that is needed
+ // for the new node. Instead, remove the data "manually".
+ if (!jQuery) {
+ delete jqLite.cache[firstElementToRemove[jqLite.expando]];
+ } else {
+ // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
+ // the replaced element. The cleanData version monkey-patched by Angular would cause
+ // the scope to be trashed and we do need the very same scope to work with the new
+ // element. However, we cannot just cache the non-patched version and use it here as
+ // that would break if another library patches the method after Angular does (one
+ // example is jQuery UI). Instead, set a flag indicating scope destroying should be
+ // skipped this one time.
+ skipDestroyOnNextJQueryCleanData = true;
+ jQuery.cleanData([firstElementToRemove]);
+ }
+
+ for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
+ var element = elementsToRemove[k];
+ jqLite(element).remove(); // must do this way to clean up expando
+ fragment.appendChild(element);
+ delete elementsToRemove[k];
+ }
+
+ elementsToRemove[0] = newNode;
+ elementsToRemove.length = 1;
+ }
+
+
+ function cloneAndAnnotateFn(fn, annotation) {
+ return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
+ }
+
+
+ function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
+ try {
+ linkFn(scope, $element, attrs, controllers, transcludeFn);
+ } catch (e) {
+ $exceptionHandler(e, startingTag($element));
+ }
+ }
+ }];
+}
+
+var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
+/**
+ * Converts all accepted directives format into proper directive name.
+ * @param name Name to normalize
+ */
+function directiveNormalize(name) {
+ return camelCase(name.replace(PREFIX_REGEXP, ''));
+}
+
+/**
+ * @ngdoc type
+ * @name $compile.directive.Attributes
+ *
+ * @description
+ * A shared object between directive compile / linking functions which contains normalized DOM
+ * element attributes. The values reflect current binding state `{{ }}`. The normalization is
+ * needed since all of these are treated as equivalent in Angular:
+ *
+ * ```
+ * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
+ * ```
+ */
+
+/**
+ * @ngdoc property
+ * @name $compile.directive.Attributes#$attr
+ *
+ * @description
+ * A map of DOM element attribute names to the normalized name. This is
+ * needed to do reverse lookup from normalized name back to actual name.
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$set
+ * @kind function
+ *
+ * @description
+ * Set DOM element attribute value.
+ *
+ *
+ * @param {string} name Normalized element attribute name of the property to modify. The name is
+ * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
+ * property to the original name.
+ * @param {string} value Value to set the attribute to. The value can be an interpolated string.
+ */
+
+
+
+/**
+ * Closure compiler type information
+ */
+
+function nodesetLinkingFn(
+ /* angular.Scope */ scope,
+ /* NodeList */ nodeList,
+ /* Element */ rootElement,
+ /* function(Function) */ boundTranscludeFn
+) {}
+
+function directiveLinkingFn(
+ /* nodesetLinkingFn */ nodesetLinkingFn,
+ /* angular.Scope */ scope,
+ /* Node */ node,
+ /* Element */ rootElement,
+ /* function(Function) */ boundTranscludeFn
+) {}
+
+function tokenDifference(str1, str2) {
+ var values = '',
+ tokens1 = str1.split(/\s+/),
+ tokens2 = str2.split(/\s+/);
+
+ outer:
+ for (var i = 0; i < tokens1.length; i++) {
+ var token = tokens1[i];
+ for (var j = 0; j < tokens2.length; j++) {
+ if (token == tokens2[j]) continue outer;
+ }
+ values += (values.length > 0 ? ' ' : '') + token;
+ }
+ return values;
+}
+
+function removeComments(jqNodes) {
+ jqNodes = jqLite(jqNodes);
+ var i = jqNodes.length;
+
+ if (i <= 1) {
+ return jqNodes;
+ }
+
+ while (i--) {
+ var node = jqNodes[i];
+ if (node.nodeType === NODE_TYPE_COMMENT) {
+ splice.call(jqNodes, i, 1);
+ }
+ }
+ return jqNodes;
+}
+
+var $controllerMinErr = minErr('$controller');
+
+/**
+ * @ngdoc provider
+ * @name $controllerProvider
+ * @description
+ * The {@link ng.$controller $controller service} is used by Angular to create new
+ * controllers.
+ *
+ * This provider allows controller registration via the
+ * {@link ng.$controllerProvider#register register} method.
+ */
+function $ControllerProvider() {
+ var controllers = {},
+ globals = false,
+ CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
+
+
+ /**
+ * @ngdoc method
+ * @name $controllerProvider#register
+ * @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|Array} constructor Controller constructor fn (optionally decorated with DI
+ * annotations in the array notation).
+ */
+ this.register = function(name, constructor) {
+ assertNotHasOwnProperty(name, 'controller');
+ if (isObject(name)) {
+ extend(controllers, name);
+ } else {
+ controllers[name] = constructor;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $controllerProvider#allowGlobals
+ * @description If called, allows `$controller` to find controller constructors on `window`
+ */
+ this.allowGlobals = function() {
+ globals = true;
+ };
+
+
+ this.$get = ['$injector', '$window', function($injector, $window) {
+
+ /**
+ * @ngdoc service
+ * @name $controller
+ * @requires $injector
+ *
+ * @param {Function|string} constructor If called with a function then it's considered to be the
+ * controller constructor function. Otherwise it's considered to be a string which is used
+ * to retrieve the controller constructor using the following steps:
+ *
+ * * check if a controller with given name is registered via `$controllerProvider`
+ * * check if evaluating the string on the current scope returns a constructor
+ * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
+ * `window` object (not recommended)
+ *
+ * The string can use the `controller as property` syntax, where the controller instance is published
+ * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
+ * to work correctly.
+ *
+ * @param {Object} locals Injection locals for Controller.
+ * @return {Object} Instance of given controller.
+ *
+ * @description
+ * `$controller` service is responsible for instantiating controllers.
+ *
+ * It's just a simple call to {@link auto.$injector $injector}, but extracted into
+ * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
+ */
+ return function(expression, locals, later, ident) {
+ // PRIVATE API:
+ // param `later` --- indicates that the controller's constructor is invoked at a later time.
+ // If true, $controller will allocate the object with the correct
+ // prototype chain, but will not invoke the controller until a returned
+ // callback is invoked.
+ // param `ident` --- An optional label which overrides the label parsed from the controller
+ // expression, if any.
+ var instance, match, constructor, identifier;
+ later = later === true;
+ if (ident && isString(ident)) {
+ identifier = ident;
+ }
+
+ if (isString(expression)) {
+ match = expression.match(CNTRL_REG);
+ if (!match) {
+ throw $controllerMinErr('ctrlfmt',
+ "Badly formed controller string '{0}'. " +
+ "Must match `__name__ as __id__` or `__name__`.", expression);
+ }
+ constructor = match[1],
+ identifier = identifier || match[3];
+ expression = controllers.hasOwnProperty(constructor)
+ ? controllers[constructor]
+ : getter(locals.$scope, constructor, true) ||
+ (globals ? getter($window, constructor, true) : undefined);
+
+ assertArgFn(expression, constructor, true);
+ }
+
+ if (later) {
+ // Instantiate controller later:
+ // This machinery is used to create an instance of the object before calling the
+ // controller's constructor itself.
+ //
+ // This allows properties to be added to the controller before the constructor is
+ // invoked. Primarily, this is used for isolate scope bindings in $compile.
+ //
+ // This feature is not intended for use by applications, and is thus not documented
+ // publicly.
+ // Object creation: http://jsperf.com/create-constructor/2
+ var controllerPrototype = (isArray(expression) ?
+ expression[expression.length - 1] : expression).prototype;
+ instance = Object.create(controllerPrototype || null);
+
+ if (identifier) {
+ addIdentifier(locals, identifier, instance, constructor || expression.name);
+ }
+
+ return extend(function() {
+ $injector.invoke(expression, instance, locals, constructor);
+ return instance;
+ }, {
+ instance: instance,
+ identifier: identifier
+ });
+ }
+
+ instance = $injector.instantiate(expression, locals, constructor);
+
+ if (identifier) {
+ addIdentifier(locals, identifier, instance, constructor || expression.name);
+ }
+
+ return instance;
+ };
+
+ function addIdentifier(locals, identifier, instance, name) {
+ if (!(locals && isObject(locals.$scope))) {
+ throw minErr('$controller')('noscp',
+ "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
+ name, identifier);
+ }
+
+ locals.$scope[identifier] = instance;
+ }
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $document
+ * @requires $window
+ *
+ * @description
+ * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
+ *
+ * @example
+ <example module="documentExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <p>$document title: <b ng-bind="title"></b></p>
+ <p>window.document title: <b ng-bind="windowTitle"></b></p>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('documentExample', [])
+ .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
+ $scope.title = $document[0].title;
+ $scope.windowTitle = angular.element(window.document)[0].title;
+ }]);
+ </file>
+ </example>
+ */
+function $DocumentProvider() {
+ this.$get = ['$window', function(window) {
+ return jqLite(window.document);
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $exceptionHandler
+ * @requires ng.$log
+ *
+ * @description
+ * Any uncaught exception in angular expressions is delegated to this service.
+ * The default implementation simply delegates to `$log.error` which logs it into
+ * the browser console.
+ *
+ * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
+ * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
+ *
+ * ## Example:
+ *
+ * ```js
+ * 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.
+ *
+ * <hr />
+ * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`
+ * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}
+ * (unless executed during a digest).
+ *
+ * If you wish, you can manually delegate exceptions, e.g.
+ * `try { ... } catch(e) { $exceptionHandler(e); }`
+ *
+ * @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);
+ };
+ }];
+}
+
+var APPLICATION_JSON = 'application/json';
+var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
+var JSON_START = /^\[|^\{(?!\{)/;
+var JSON_ENDS = {
+ '[': /]$/,
+ '{': /}$/
+};
+var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
+
+function defaultHttpResponseTransform(data, headers) {
+ if (isString(data)) {
+ // Strip json vulnerability protection prefix and trim whitespace
+ var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
+
+ if (tempData) {
+ var contentType = headers('Content-Type');
+ if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
+ data = fromJson(tempData);
+ }
+ }
+ }
+
+ return data;
+}
+
+function isJsonLike(str) {
+ var jsonStart = str.match(JSON_START);
+ return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
+}
+
+/**
+ * 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 = createMap(), 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) {
+ parsed[key] = parsed[key] ? parsed[key] + ', ' + val : 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) {
+ var value = headersObj[lowercase(name)];
+ if (value === void 0) {
+ value = null;
+ }
+ return value;
+ }
+
+ 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 {number} status HTTP status code of the response.
+ * @param {(Function|Array.<Function>)} fns Function or an array of functions.
+ * @returns {*} Transformed data.
+ */
+function transformData(data, headers, status, fns) {
+ if (isFunction(fns))
+ return fns(data, headers, status);
+
+ forEach(fns, function(fn) {
+ data = fn(data, headers, status);
+ });
+
+ return data;
+}
+
+
+function isSuccess(status) {
+ return 200 <= status && status < 300;
+}
+
+
+/**
+ * @ngdoc provider
+ * @name $httpProvider
+ * @description
+ * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
+ * */
+function $HttpProvider() {
+ /**
+ * @ngdoc property
+ * @name $httpProvider#defaults
+ * @description
+ *
+ * Object containing default values for all {@link ng.$http $http} requests.
+ *
+ * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
+ * that will provide the cache for all requests who set their `cache` property to `true`.
+ * If you set the `default.cache = false` then only requests that specify their own custom
+ * cache object will be cached. See {@link $http#caching $http Caching} for more information.
+ *
+ * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
+ * Defaults value is `'XSRF-TOKEN'`.
+ *
+ * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
+ * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
+ *
+ * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
+ * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
+ * setting default headers.
+ * - **`defaults.headers.common`**
+ * - **`defaults.headers.post`**
+ * - **`defaults.headers.put`**
+ * - **`defaults.headers.patch`**
+ *
+ **/
+ var defaults = this.defaults = {
+ // transform incoming response data
+ transformResponse: [defaultHttpResponseTransform],
+
+ // transform outgoing request data
+ transformRequest: [function(d) {
+ return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
+ }],
+
+ // default headers
+ headers: {
+ common: {
+ 'Accept': 'application/json, text/plain, */*'
+ },
+ post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
+ put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
+ patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
+ },
+
+ xsrfCookieName: 'XSRF-TOKEN',
+ xsrfHeaderName: 'X-XSRF-TOKEN'
+ };
+
+ var useApplyAsync = false;
+ /**
+ * @ngdoc method
+ * @name $httpProvider#useApplyAsync
+ * @description
+ *
+ * Configure $http service to combine processing of multiple http responses received at around
+ * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in
+ * significant performance improvement for bigger applications that make many HTTP requests
+ * concurrently (common during application bootstrap).
+ *
+ * Defaults to false. If no value is specifed, returns the current configured value.
+ *
+ * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred
+ * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window
+ * to load and share the same digest cycle.
+ *
+ * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
+ * otherwise, returns the current configured value.
+ **/
+ this.useApplyAsync = function(value) {
+ if (isDefined(value)) {
+ useApplyAsync = !!value;
+ return this;
+ }
+ return useApplyAsync;
+ };
+
+ /**
+ * @ngdoc property
+ * @name $httpProvider#interceptors
+ * @description
+ *
+ * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
+ * pre-processing of request or postprocessing of responses.
+ *
+ * These service factories are ordered by request, i.e. they are applied in the same order as the
+ * array, on request, but reverse order, on response.
+ *
+ * {@link ng.$http#interceptors Interceptors detailed info}
+ **/
+ var interceptorFactories = this.interceptors = [];
+
+ this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
+ function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
+
+ var defaultCache = $cacheFactory('$http');
+
+ /**
+ * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
+ * The reversal is needed so that we can build up the interception chain around the
+ * server request.
+ */
+ var reversedInterceptors = [];
+
+ forEach(interceptorFactories, function(interceptorFactory) {
+ reversedInterceptors.unshift(isString(interceptorFactory)
+ ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
+ });
+
+ /**
+ * @ngdoc service
+ * @kind function
+ * @name $http
+ * @requires ng.$httpBackend
+ * @requires $cacheFactory
+ * @requires $rootScope
+ * @requires $q
+ * @requires $injector
+ *
+ * @description
+ * The `$http` service is a core Angular service that facilitates communication with the remote
+ * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
+ * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
+ *
+ * For unit testing applications that use `$http` service, see
+ * {@link ngMock.$httpBackend $httpBackend mock}.
+ *
+ * For a higher level of abstraction, please check out the {@link ngResource.$resource
+ * $resource} service.
+ *
+ * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
+ * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
+ * it is important to familiarize yourself with these APIs and the guarantees they provide.
+ *
+ *
+ * ## General usage
+ * The `$http` service is a function which takes a single argument — a configuration object —
+ * that is used to generate an HTTP request and returns a {@link ng.$q promise}
+ * with two $http specific methods: `success` and `error`.
+ *
+ * ```js
+ * // Simple GET request example :
+ * $http.get('/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.
+ * });
+ * ```
+ *
+ * ```js
+ * // Simple POST request example (passing data) :
+ * $http.post('/someUrl', {msg:'hello word!'}).
+ * 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.
+ *
+ * ## Writing Unit Tests that use $http
+ * When unit testing (using {@link ngMock ngMock}), it is necessary to call
+ * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
+ * request using trained responses.
+ *
+ * ```
+ * $httpBackend.expectGET(...);
+ * $http.get(...);
+ * $httpBackend.flush();
+ * ```
+ *
+ * ## Shortcut methods
+ *
+ * Shortcut methods are also available. All shortcut methods require passing in the URL, and
+ * request data must be passed in for POST/PUT requests.
+ *
+ * ```js
+ * $http.get('/someUrl').success(successCallback);
+ * $http.post('/someUrl', data).success(successCallback);
+ * ```
+ *
+ * Complete list of shortcut methods:
+ *
+ * - {@link ng.$http#get $http.get}
+ * - {@link ng.$http#head $http.head}
+ * - {@link ng.$http#post $http.post}
+ * - {@link ng.$http#put $http.put}
+ * - {@link ng.$http#delete $http.delete}
+ * - {@link ng.$http#jsonp $http.jsonp}
+ * - {@link ng.$http#patch $http.patch}
+ *
+ *
+ * ## 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. For example:
+ *
+ * ```
+ * module.run(function($http) {
+ * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
+ * });
+ * ```
+ *
+ * In addition, you can supply a `headers` property in the config object passed when
+ * calling `$http(config)`, which overrides the defaults without changing them globally.
+ *
+ * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
+ * Use the `headers` property, setting the desired header to `undefined`. For example:
+ *
+ * ```js
+ * var req = {
+ * method: 'POST',
+ * url: 'http://example.com',
+ * headers: {
+ * 'Content-Type': undefined
+ * },
+ * data: { test: 'test' }
+ * }
+ *
+ * $http(req).success(function(){...}).error(function(){...});
+ * ```
+ *
+ * ## Transforming Requests and Responses
+ *
+ * Both requests and responses can be transformed using transformation functions: `transformRequest`
+ * and `transformResponse`. These properties can be a single function that returns
+ * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,
+ * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
+ *
+ * ### Default Transformations
+ *
+ * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
+ * `defaults.transformResponse` properties. If a request does not provide its own transformations
+ * then these will be applied.
+ *
+ * You can augment or replace the default transformations by modifying these properties by adding to or
+ * replacing the array.
+ *
+ * Angular provides the following default transformations:
+ *
+ * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
+ *
+ * - If the `data` property of the request configuration object contains an object, serialize it
+ * into JSON format.
+ *
+ * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
+ *
+ * - If XSRF prefix is detected, strip it (see Security Considerations section below).
+ * - If JSON response is detected, deserialize it using a JSON parser.
+ *
+ *
+ * ### Overriding the Default Transformations Per Request
+ *
+ * If you wish override the request/response transformations only for a single request then provide
+ * `transformRequest` and/or `transformResponse` properties on the configuration object passed
+ * into `$http`.
+ *
+ * Note that if you provide these properties on the config object the default transformations will be
+ * overwritten. If you wish to augment the default transformations then you must include them in your
+ * local transformation array.
+ *
+ * The following code demonstrates adding a new response transformation to be run after the default response
+ * transformations have been run.
+ *
+ * ```js
+ * function appendTransform(defaults, transform) {
+ *
+ * // We can't guarantee that the default transformation is an array
+ * defaults = angular.isArray(defaults) ? defaults : [defaults];
+ *
+ * // Append the new transformation to the defaults
+ * return defaults.concat(transform);
+ * }
+ *
+ * $http({
+ * url: '...',
+ * method: 'GET',
+ * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
+ * return doTransform(value);
+ * })
+ * });
+ * ```
+ *
+ *
+ * ## Caching
+ *
+ * To enable caching, set the request configuration `cache` property to `true` (to use default
+ * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
+ * When the cache is enabled, `$http` stores the response from the server in the specified
+ * cache. The next time the same request is made, 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.
+ *
+ * You can change the default cache to a new object (built with
+ * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
+ * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set
+ * their `cache` property to `true` will now use this cache object.
+ *
+ * If you set the default cache to `false` then only requests that specify their own custom
+ * cache object will be cached.
+ *
+ * ## 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 a http `config` object. The function is free to
+ * modify the `config` object or create a new one. The function needs to return the `config`
+ * object directly, or a promise containing the `config` or a new `config` object.
+ * * `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` object or create a new one. The function needs to return the `response`
+ * object directly, or as a promise containing the `response` or a new `response` object.
+ * * `responseError`: interceptor gets called when a previous interceptor threw an error or
+ * resolved with a rejection.
+ *
+ *
+ * ```js
+ * // 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;
+ * },
+ *
+ * // 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;
+ * },
+ *
+ * // optional method
+ * 'responseError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * }
+ * };
+ * });
+ *
+ * $httpProvider.interceptors.push('myHttpInterceptor');
+ *
+ *
+ * // alternatively, 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
+ * }
+ * };
+ * });
+ * ```
+ *
+ * ## Security Considerations
+ *
+ * When designing web applications, consider security threats from:
+ *
+ * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
+ * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
+ *
+ * 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 [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
+ * allows third party website to turn your JSON resource URL into
+ * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
+ * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
+ * Angular will automatically strip the prefix before processing it as JSON.
+ *
+ * For example if your server needs to return:
+ * ```js
+ * ['one','two']
+ * ```
+ *
+ * which is vulnerable to attack, your server can return:
+ * ```js
+ * )]}',
+ * ['one','two']
+ * ```
+ *
+ * Angular will strip the prefix, before processing the JSON.
+ *
+ *
+ * ### Cross Site Request Forgery (XSRF) Protection
+ *
+ * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) 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 [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
+ * for added security.
+ *
+ * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
+ * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
+ * or the per-request config object.
+ *
+ *
+ * @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.<string|Object>}` – Map of strings or objects which will be turned
+ * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
+ * JSONified.
+ * - **data** – `{string|Object}` – Data to be sent as the request message data.
+ * - **headers** – `{Object}` – Map of strings or functions which return strings representing
+ * HTTP headers to send to the server. If the return value of a function is null, the
+ * header will not be sent.
+ * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
+ * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
+ * - **transformRequest** –
+ * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
+ * transform function or an array of such functions. The transform function takes the http
+ * request body and headers and returns its transformed (typically serialized) version.
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
+ * Overriding the Default Transformations}
+ * - **transformResponse** –
+ * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
+ * transform function or an array of such functions. The transform function takes the http
+ * response body, headers and status and returns its transformed (typically deserialized) version.
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
+ * Overriding the Default Transformations}
+ * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
+ * GET request, otherwise if a cache instance built with
+ * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
+ * caching.
+ * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
+ * that should abort the request when resolved.
+ * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
+ * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
+ * for more information.
+ * - **responseType** - `{string}` - see
+ * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
+ *
+ * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
+ * standard `then` method and two http specific methods: `success` and `error`. The `then`
+ * method takes two arguments a success and an error callback which will be called with a
+ * response object. The `success` and `error` methods take a single argument - a function that
+ * will be called when the request succeeds or fails respectively. The arguments passed into
+ * these functions are destructured representation of the response object passed into the
+ * `then` method. The response object has these properties:
+ *
+ * - **data** – `{string|Object}` – The response body transformed with the transform
+ * functions.
+ * - **status** – `{number}` – HTTP status code of the response.
+ * - **headers** – `{function([headerName])}` – Header getter function.
+ * - **config** – `{Object}` – The configuration object that was used to generate the request.
+ * - **statusText** – `{string}` – HTTP status text of the response.
+ *
+ * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
+ * requests. This is primarily meant to be used for debugging purposes.
+ *
+ *
+ * @example
+<example module="httpExample">
+<file name="index.html">
+ <div ng-controller="FetchController">
+ <select ng-model="method">
+ <option>GET</option>
+ <option>JSONP</option>
+ </select>
+ <input type="text" ng-model="url" size="80"/>
+ <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
+ <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
+ <button id="samplejsonpbtn"
+ ng-click="updateModel('JSONP',
+ 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
+ Sample JSONP
+ </button>
+ <button id="invalidjsonpbtn"
+ ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
+ Invalid JSONP
+ </button>
+ <pre>http status code: {{status}}</pre>
+ <pre>http response data: {{data}}</pre>
+ </div>
+</file>
+<file name="script.js">
+ angular.module('httpExample', [])
+ .controller('FetchController', ['$scope', '$http', '$templateCache',
+ function($scope, $http, $templateCache) {
+ $scope.method = 'GET';
+ $scope.url = 'http-hello.html';
+
+ $scope.fetch = function() {
+ $scope.code = null;
+ $scope.response = null;
+
+ $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
+ success(function(data, status) {
+ $scope.status = status;
+ $scope.data = data;
+ }).
+ error(function(data, status) {
+ $scope.data = data || "Request failed";
+ $scope.status = status;
+ });
+ };
+
+ $scope.updateModel = function(method, url) {
+ $scope.method = method;
+ $scope.url = url;
+ };
+ }]);
+</file>
+<file name="http-hello.html">
+ Hello, $http!
+</file>
+<file name="protractor.js" type="protractor">
+ var status = element(by.binding('status'));
+ var data = element(by.binding('data'));
+ var fetchBtn = element(by.id('fetchbtn'));
+ var sampleGetBtn = element(by.id('samplegetbtn'));
+ var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
+ var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));
+
+ it('should make an xhr GET request', function() {
+ sampleGetBtn.click();
+ fetchBtn.click();
+ expect(status.getText()).toMatch('200');
+ expect(data.getText()).toMatch(/Hello, \$http!/);
+ });
+
+// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185
+// it('should make a JSONP request to angularjs.org', function() {
+// sampleJsonpBtn.click();
+// fetchBtn.click();
+// expect(status.getText()).toMatch('200');
+// expect(data.getText()).toMatch(/Super Hero!/);
+// });
+
+ it('should make JSONP request to invalid URL and invoke the error handler',
+ function() {
+ invalidJsonpBtn.click();
+ fetchBtn.click();
+ expect(status.getText()).toMatch('0');
+ expect(data.getText()).toMatch('Request failed');
+ });
+</file>
+</example>
+ */
+ function $http(requestConfig) {
+
+ if (!angular.isObject(requestConfig)) {
+ throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
+ }
+
+ var config = extend({
+ method: 'get',
+ transformRequest: defaults.transformRequest,
+ transformResponse: defaults.transformResponse
+ }, requestConfig);
+
+ config.headers = mergeHeaders(requestConfig);
+ config.method = uppercase(config.method);
+
+ var serverRequest = function(config) {
+ var headers = config.headers;
+ var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
+
+ // strip content-type if data is undefined
+ if (isUndefined(reqData)) {
+ forEach(headers, function(value, header) {
+ if (lowercase(header) === 'content-type') {
+ delete headers[header];
+ }
+ });
+ }
+
+ if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
+ config.withCredentials = defaults.withCredentials;
+ }
+
+ // send request
+ return sendReq(config, reqData).then(transformResponse, transformResponse);
+ };
+
+ var chain = [serverRequest, undefined];
+ var promise = $q.when(config);
+
+ // apply interceptors
+ forEach(reversedInterceptors, function(interceptor) {
+ if (interceptor.request || interceptor.requestError) {
+ chain.unshift(interceptor.request, interceptor.requestError);
+ }
+ if (interceptor.response || interceptor.responseError) {
+ chain.push(interceptor.response, interceptor.responseError);
+ }
+ });
+
+ while (chain.length) {
+ var thenFn = chain.shift();
+ var rejectFn = chain.shift();
+
+ promise = promise.then(thenFn, rejectFn);
+ }
+
+ promise.success = function(fn) {
+ assertArgFn(fn, 'fn');
+
+ promise.then(function(response) {
+ fn(response.data, response.status, response.headers, config);
+ });
+ return promise;
+ };
+
+ promise.error = function(fn) {
+ assertArgFn(fn, 'fn');
+
+ promise.then(null, function(response) {
+ fn(response.data, response.status, response.headers, config);
+ });
+ return promise;
+ };
+
+ return promise;
+
+ function transformResponse(response) {
+ // make a copy since the response must be cacheable
+ var resp = extend({}, response);
+ if (!response.data) {
+ resp.data = response.data;
+ } else {
+ resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
+ }
+ return (isSuccess(response.status))
+ ? resp
+ : $q.reject(resp);
+ }
+
+ function executeHeaderFns(headers) {
+ var headerContent, processedHeaders = {};
+
+ forEach(headers, function(headerFn, header) {
+ if (isFunction(headerFn)) {
+ headerContent = headerFn();
+ if (headerContent != null) {
+ processedHeaders[header] = headerContent;
+ }
+ } else {
+ processedHeaders[header] = headerFn;
+ }
+ });
+
+ return processedHeaders;
+ }
+
+ function mergeHeaders(config) {
+ var defHeaders = defaults.headers,
+ reqHeaders = extend({}, config.headers),
+ defHeaderName, lowercaseDefHeaderName, reqHeaderName;
+
+ defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
+
+ // using for-in instead of forEach to avoid unecessary iteration after header has been found
+ defaultHeadersIteration:
+ for (defHeaderName in defHeaders) {
+ lowercaseDefHeaderName = lowercase(defHeaderName);
+
+ for (reqHeaderName in reqHeaders) {
+ if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
+ continue defaultHeadersIteration;
+ }
+ }
+
+ reqHeaders[defHeaderName] = defHeaders[defHeaderName];
+ }
+
+ // execute if header value is a function for merged headers
+ return executeHeaderFns(reqHeaders);
+ }
+ }
+
+ $http.pendingRequests = [];
+
+ /**
+ * @ngdoc method
+ * @name $http#get
+ *
+ * @description
+ * Shortcut method to perform `GET` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#delete
+ *
+ * @description
+ * Shortcut method to perform `DELETE` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#head
+ *
+ * @description
+ * Shortcut method to perform `HEAD` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#jsonp
+ *
+ * @description
+ * Shortcut method to perform `JSONP` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request.
+ * The name of the callback should be the string `JSON_CALLBACK`.
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+ createShortMethods('get', 'delete', 'head', 'jsonp');
+
+ /**
+ * @ngdoc method
+ * @name $http#post
+ *
+ * @description
+ * Shortcut method to perform `POST` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#put
+ *
+ * @description
+ * Shortcut method to perform `PUT` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#patch
+ *
+ * @description
+ * Shortcut method to perform `PATCH` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+ createShortMethodsWithData('post', 'put', 'patch');
+
+ /**
+ * @ngdoc property
+ * @name $http#defaults
+ *
+ * @description
+ * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
+ * default headers, withCredentials as well as request and response transformations.
+ *
+ * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
+ */
+ $http.defaults = defaults;
+
+
+ return $http;
+
+
+ function createShortMethods(names) {
+ forEach(arguments, function(name) {
+ $http[name] = function(url, config) {
+ return $http(extend(config || {}, {
+ method: name,
+ url: url
+ }));
+ };
+ });
+ }
+
+
+ function createShortMethodsWithData(name) {
+ forEach(arguments, function(name) {
+ $http[name] = function(url, data, config) {
+ return $http(extend(config || {}, {
+ method: name,
+ url: url,
+ data: data
+ }));
+ };
+ });
+ }
+
+
+ /**
+ * Makes the request.
+ *
+ * !!! ACCESSES CLOSURE VARS:
+ * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
+ */
+ function sendReq(config, reqData) {
+ var deferred = $q.defer(),
+ promise = deferred.promise,
+ cache,
+ cachedResp,
+ reqHeaders = config.headers,
+ url = buildUrl(config.url, config.params);
+
+ $http.pendingRequests.push(config);
+ promise.then(removePendingReq, removePendingReq);
+
+
+ if ((config.cache || defaults.cache) && config.cache !== false &&
+ (config.method === 'GET' || config.method === 'JSONP')) {
+ cache = isObject(config.cache) ? config.cache
+ : isObject(defaults.cache) ? defaults.cache
+ : defaultCache;
+ }
+
+ if (cache) {
+ cachedResp = cache.get(url);
+ if (isDefined(cachedResp)) {
+ if (isPromiseLike(cachedResp)) {
+ // cached request has already been sent, but there is no response yet
+ cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
+ } else {
+ // serving from cache
+ if (isArray(cachedResp)) {
+ resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
+ } else {
+ resolvePromise(cachedResp, 200, {}, 'OK');
+ }
+ }
+ } else {
+ // put the promise for the non-transformed response into cache as a placeholder
+ cache.put(url, promise);
+ }
+ }
+
+
+ // if we won't have the response in cache, set the xsrf headers and
+ // send the request to the backend
+ if (isUndefined(cachedResp)) {
+ var xsrfValue = urlIsSameOrigin(config.url)
+ ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
+ : undefined;
+ if (xsrfValue) {
+ reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
+ }
+
+ $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
+ config.withCredentials, config.responseType);
+ }
+
+ return promise;
+
+
+ /**
+ * Callback registered to $httpBackend():
+ * - caches the response if desired
+ * - resolves the raw $http promise
+ * - calls $apply
+ */
+ function done(status, response, headersString, statusText) {
+ if (cache) {
+ if (isSuccess(status)) {
+ cache.put(url, [status, response, parseHeaders(headersString), statusText]);
+ } else {
+ // remove promise from the cache
+ cache.remove(url);
+ }
+ }
+
+ function resolveHttpPromise() {
+ resolvePromise(response, status, headersString, statusText);
+ }
+
+ if (useApplyAsync) {
+ $rootScope.$applyAsync(resolveHttpPromise);
+ } else {
+ resolveHttpPromise();
+ if (!$rootScope.$$phase) $rootScope.$apply();
+ }
+ }
+
+
+ /**
+ * Resolves the raw $http promise.
+ */
+ function resolvePromise(response, status, headers, statusText) {
+ //status: HTTP response status code, 0, -1 (aborted by timeout / promise)
+ status = status >= -1 ? status : 0;
+
+ (isSuccess(status) ? deferred.resolve : deferred.reject)({
+ data: response,
+ status: status,
+ headers: headersGetter(headers),
+ config: config,
+ statusText: statusText
+ });
+ }
+
+ function resolvePromiseWithResult(result) {
+ resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
+ }
+
+ function removePendingReq() {
+ var idx = $http.pendingRequests.indexOf(config);
+ if (idx !== -1) $http.pendingRequests.splice(idx, 1);
+ }
+ }
+
+
+ function buildUrl(url, params) {
+ if (!params) return url;
+ var parts = [];
+ forEachSorted(params, function(value, key) {
+ if (value === null || isUndefined(value)) return;
+ if (!isArray(value)) value = [value];
+
+ forEach(value, function(v) {
+ if (isObject(v)) {
+ if (isDate(v)) {
+ v = v.toISOString();
+ } else {
+ v = toJson(v);
+ }
+ }
+ parts.push(encodeUriQuery(key) + '=' +
+ encodeUriQuery(v));
+ });
+ });
+ if (parts.length > 0) {
+ url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
+ }
+ return url;
+ }
+ }];
+}
+
+function createXhr() {
+ return new window.XMLHttpRequest();
+}
+
+/**
+ * @ngdoc service
+ * @name $httpBackend
+ * @requires $window
+ * @requires $document
+ *
+ * @description
+ * HTTP backend used by the {@link ng.$http service} that delegates to
+ * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
+ *
+ * You should never need to use this service directly, instead use the higher-level abstractions:
+ * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
+ *
+ * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
+ * $httpBackend} which can be trained with responses.
+ */
+function $HttpBackendProvider() {
+ this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
+ return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
+ }];
+}
+
+function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
+ // TODO(vojta): fix the signature
+ return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
+ $browser.$$incOutstandingRequestCount();
+ url = url || $browser.url();
+
+ if (lowercase(method) == 'jsonp') {
+ var callbackId = '_' + (callbacks.counter++).toString(36);
+ callbacks[callbackId] = function(data) {
+ callbacks[callbackId].data = data;
+ callbacks[callbackId].called = true;
+ };
+
+ var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
+ callbackId, function(status, text) {
+ completeRequest(callback, status, callbacks[callbackId].data, "", text);
+ callbacks[callbackId] = noop;
+ });
+ } else {
+
+ var xhr = createXhr();
+
+ xhr.open(method, url, true);
+ forEach(headers, function(value, key) {
+ if (isDefined(value)) {
+ xhr.setRequestHeader(key, value);
+ }
+ });
+
+ xhr.onload = function requestLoaded() {
+ var statusText = xhr.statusText || '';
+
+ // responseText is the old-school way of retrieving response (supported by IE9)
+ // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
+ var response = ('response' in xhr) ? xhr.response : xhr.responseText;
+
+ // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
+ var status = xhr.status === 1223 ? 204 : xhr.status;
+
+ // fix status code when it is 0 (0 status is undocumented).
+ // Occurs when accessing file resources or on Android 4.1 stock browser
+ // while retrieving files from application cache.
+ if (status === 0) {
+ status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
+ }
+
+ completeRequest(callback,
+ status,
+ response,
+ xhr.getAllResponseHeaders(),
+ statusText);
+ };
+
+ var requestError = function() {
+ // The response is always empty
+ // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
+ completeRequest(callback, -1, null, null, '');
+ };
+
+ xhr.onerror = requestError;
+ xhr.onabort = requestError;
+
+ if (withCredentials) {
+ xhr.withCredentials = true;
+ }
+
+ if (responseType) {
+ try {
+ xhr.responseType = responseType;
+ } catch (e) {
+ // WebKit added support for the json responseType value on 09/03/2013
+ // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
+ // known to throw when setting the value "json" as the response type. Other older
+ // browsers implementing the responseType
+ //
+ // The json response type can be ignored if not supported, because JSON payloads are
+ // parsed on the client-side regardless.
+ if (responseType !== 'json') {
+ throw e;
+ }
+ }
+ }
+
+ xhr.send(post || null);
+ }
+
+ if (timeout > 0) {
+ var timeoutId = $browserDefer(timeoutRequest, timeout);
+ } else if (isPromiseLike(timeout)) {
+ timeout.then(timeoutRequest);
+ }
+
+
+ function timeoutRequest() {
+ jsonpDone && jsonpDone();
+ xhr && xhr.abort();
+ }
+
+ function completeRequest(callback, status, response, headersString, statusText) {
+ // cancel timeout and subsequent timeout promise resolution
+ if (timeoutId !== undefined) {
+ $browserDefer.cancel(timeoutId);
+ }
+ jsonpDone = xhr = null;
+
+ callback(status, response, headersString, statusText);
+ $browser.$$completeOutstandingRequest(noop);
+ }
+ };
+
+ function jsonpReq(url, callbackId, done) {
+ // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
+ // - fetches local scripts via XHR and evals them
+ // - adds and immediately removes script elements from the document
+ var script = rawDocument.createElement('script'), callback = null;
+ script.type = "text/javascript";
+ script.src = url;
+ script.async = true;
+
+ callback = function(event) {
+ removeEventListenerFn(script, "load", callback);
+ removeEventListenerFn(script, "error", callback);
+ rawDocument.body.removeChild(script);
+ script = null;
+ var status = -1;
+ var text = "unknown";
+
+ if (event) {
+ if (event.type === "load" && !callbacks[callbackId].called) {
+ event = { type: "error" };
+ }
+ text = event.type;
+ status = event.type === "error" ? 404 : 200;
+ }
+
+ if (done) {
+ done(status, text);
+ }
+ };
+
+ addEventListenerFn(script, "load", callback);
+ addEventListenerFn(script, "error", callback);
+ rawDocument.body.appendChild(script);
+ return callback;
+ }
+}
+
+var $interpolateMinErr = minErr('$interpolate');
+
+/**
+ * @ngdoc provider
+ * @name $interpolateProvider
+ *
+ * @description
+ *
+ * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
+ *
+ * @example
+<example module="customInterpolationApp">
+<file name="index.html">
+<script>
+ var customInterpolationApp = angular.module('customInterpolationApp', []);
+
+ customInterpolationApp.config(function($interpolateProvider) {
+ $interpolateProvider.startSymbol('//');
+ $interpolateProvider.endSymbol('//');
+ });
+
+
+ customInterpolationApp.controller('DemoController', function() {
+ this.label = "This binding is brought you by // interpolation symbols.";
+ });
+</script>
+<div ng-app="App" ng-controller="DemoController as demo">
+ //demo.label//
+</div>
+</file>
+<file name="protractor.js" type="protractor">
+ it('should interpolate binding with custom symbols', function() {
+ expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
+ });
+</file>
+</example>
+ */
+function $InterpolateProvider() {
+ var startSymbol = '{{';
+ var endSymbol = '}}';
+
+ /**
+ * @ngdoc method
+ * @name $interpolateProvider#startSymbol
+ * @description
+ * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
+ *
+ * @param {string=} value new value to set the starting symbol to.
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
+ */
+ this.startSymbol = function(value) {
+ if (value) {
+ startSymbol = value;
+ return this;
+ } else {
+ return startSymbol;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $interpolateProvider#endSymbol
+ * @description
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
+ *
+ * @param {string=} value new value to set the ending symbol to.
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
+ */
+ this.endSymbol = function(value) {
+ if (value) {
+ endSymbol = value;
+ return this;
+ } else {
+ return endSymbol;
+ }
+ };
+
+
+ this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
+ var startSymbolLength = startSymbol.length,
+ endSymbolLength = endSymbol.length,
+ escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),
+ escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');
+
+ function escape(ch) {
+ return '\\\\\\' + ch;
+ }
+
+ /**
+ * @ngdoc service
+ * @name $interpolate
+ * @kind function
+ *
+ * @requires $parse
+ * @requires $sce
+ *
+ * @description
+ *
+ * Compiles a string with markup into an interpolation function. This service is used by the
+ * HTML {@link ng.$compile $compile} service for data binding. See
+ * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
+ * interpolation markup.
+ *
+ *
+ * ```js
+ * var $interpolate = ...; // injected
+ * var exp = $interpolate('Hello {{name | uppercase}}!');
+ * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
+ * ```
+ *
+ * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
+ * `true`, the interpolation function will return `undefined` unless all embedded expressions
+ * evaluate to a value other than `undefined`.
+ *
+ * ```js
+ * var $interpolate = ...; // injected
+ * var context = {greeting: 'Hello', name: undefined };
+ *
+ * // default "forgiving" mode
+ * var exp = $interpolate('{{greeting}} {{name}}!');
+ * expect(exp(context)).toEqual('Hello !');
+ *
+ * // "allOrNothing" mode
+ * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
+ * expect(exp(context)).toBeUndefined();
+ * context.name = 'Angular';
+ * expect(exp(context)).toEqual('Hello Angular!');
+ * ```
+ *
+ * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
+ *
+ * ####Escaped Interpolation
+ * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
+ * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
+ * It will be rendered as a regular start/end marker, and will not be interpreted as an expression
+ * or binding.
+ *
+ * This enables web-servers to prevent script injection attacks and defacing attacks, to some
+ * degree, while also enabling code examples to work without relying on the
+ * {@link ng.directive:ngNonBindable ngNonBindable} directive.
+ *
+ * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
+ * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
+ * interpolation start/end markers with their escaped counterparts.**
+ *
+ * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
+ * output when the $interpolate service processes the text. So, for HTML elements interpolated
+ * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
+ * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
+ * this is typically useful only when user-data is used in rendering a template from the server, or
+ * when otherwise untrusted data is used by a directive.
+ *
+ * <example>
+ * <file name="index.html">
+ * <div ng-init="username='A user'">
+ * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
+ * </p>
+ * <p><strong>{{username}}</strong> attempts to inject code which will deface the
+ * application, but fails to accomplish their task, because the server has correctly
+ * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
+ * characters.</p>
+ * <p>Instead, the result of the attempted script injection is visible, and can be removed
+ * from the database by an administrator.</p>
+ * </div>
+ * </file>
+ * </example>
+ *
+ * @param {string} text The text with markup to interpolate.
+ * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
+ * embedded expression in order to return an interpolation function. Strings with no
+ * embedded expression will return null for the interpolation function.
+ * @param {string=} trustedContext when provided, the returned function passes the interpolated
+ * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
+ * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
+ * provides Strict Contextual Escaping for details.
+ * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
+ * unless all embedded expressions evaluate to a value other than `undefined`.
+ * @returns {function(context)} an interpolation function which is used to compute the
+ * interpolated string. The function has these parameters:
+ *
+ * - `context`: evaluation context for all expressions embedded in the interpolated text
+ */
+ function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
+ allOrNothing = !!allOrNothing;
+ var startIndex,
+ endIndex,
+ index = 0,
+ expressions = [],
+ parseFns = [],
+ textLength = text.length,
+ exp,
+ concat = [],
+ expressionPositions = [];
+
+ while (index < textLength) {
+ if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
+ ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
+ if (index !== startIndex) {
+ concat.push(unescapeText(text.substring(index, startIndex)));
+ }
+ exp = text.substring(startIndex + startSymbolLength, endIndex);
+ expressions.push(exp);
+ parseFns.push($parse(exp, parseStringifyInterceptor));
+ index = endIndex + endSymbolLength;
+ expressionPositions.push(concat.length);
+ concat.push('');
+ } else {
+ // we did not find an interpolation, so we have to add the remainder to the separators array
+ if (index !== textLength) {
+ concat.push(unescapeText(text.substring(index)));
+ }
+ break;
+ }
+ }
+
+ // Concatenating expressions makes it hard to reason about whether some combination of
+ // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
+ // single expression be used for iframe[src], object[src], etc., we ensure that the value
+ // that's used is assigned or constructed by some JS code somewhere that is more testable or
+ // make it obvious that you bound the value to some user controlled value. This helps reduce
+ // the load when auditing for XSS issues.
+ if (trustedContext && concat.length > 1) {
+ throw $interpolateMinErr('noconcat',
+ "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
+ "interpolations that concatenate multiple expressions when a trusted value is " +
+ "required. See http://docs.angularjs.org/api/ng.$sce", text);
+ }
+
+ if (!mustHaveExpression || expressions.length) {
+ var compute = function(values) {
+ for (var i = 0, ii = expressions.length; i < ii; i++) {
+ if (allOrNothing && isUndefined(values[i])) return;
+ concat[expressionPositions[i]] = values[i];
+ }
+ return concat.join('');
+ };
+
+ var getValue = function(value) {
+ return trustedContext ?
+ $sce.getTrusted(trustedContext, value) :
+ $sce.valueOf(value);
+ };
+
+ var stringify = function(value) {
+ if (value == null) { // null || undefined
+ return '';
+ }
+ switch (typeof value) {
+ case 'string':
+ break;
+ case 'number':
+ value = '' + value;
+ break;
+ default:
+ value = toJson(value);
+ }
+
+ return value;
+ };
+
+ return extend(function interpolationFn(context) {
+ var i = 0;
+ var ii = expressions.length;
+ var values = new Array(ii);
+
+ try {
+ for (; i < ii; i++) {
+ values[i] = parseFns[i](context);
+ }
+
+ return compute(values);
+ } catch (err) {
+ var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
+ err.toString());
+ $exceptionHandler(newErr);
+ }
+
+ }, {
+ // all of these properties are undocumented for now
+ exp: text, //just for compatibility with regular watchers created via $watch
+ expressions: expressions,
+ $$watchDelegate: function(scope, listener, objectEquality) {
+ var lastValue;
+ return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
+ var currValue = compute(values);
+ if (isFunction(listener)) {
+ listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
+ }
+ lastValue = currValue;
+ }, objectEquality);
+ }
+ });
+ }
+
+ function unescapeText(text) {
+ return text.replace(escapedStartRegexp, startSymbol).
+ replace(escapedEndRegexp, endSymbol);
+ }
+
+ function parseStringifyInterceptor(value) {
+ try {
+ value = getValue(value);
+ return allOrNothing && !isDefined(value) ? value : stringify(value);
+ } catch (err) {
+ var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
+ err.toString());
+ $exceptionHandler(newErr);
+ }
+ }
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $interpolate#startSymbol
+ * @description
+ * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
+ *
+ * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
+ * the symbol.
+ *
+ * @returns {string} start symbol.
+ */
+ $interpolate.startSymbol = function() {
+ return startSymbol;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $interpolate#endSymbol
+ * @description
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
+ *
+ * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
+ * the symbol.
+ *
+ * @returns {string} end symbol.
+ */
+ $interpolate.endSymbol = function() {
+ return endSymbol;
+ };
+
+ return $interpolate;
+ }];
+}
+
+function $IntervalProvider() {
+ this.$get = ['$rootScope', '$window', '$q', '$$q',
+ function($rootScope, $window, $q, $$q) {
+ var intervals = {};
+
+
+ /**
+ * @ngdoc service
+ * @name $interval
+ *
+ * @description
+ * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
+ * milliseconds.
+ *
+ * The return value of registering an interval function is a promise. This promise will be
+ * notified upon each tick of the interval, and will be resolved after `count` iterations, or
+ * run indefinitely if `count` is not defined. The value of the notification will be the
+ * number of iterations that have run.
+ * To cancel an interval, call `$interval.cancel(promise)`.
+ *
+ * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
+ * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
+ * time.
+ *
+ * <div class="alert alert-warning">
+ * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
+ * with them. In particular they are not automatically destroyed when a controller's scope or a
+ * directive's element are destroyed.
+ * You should take this into consideration and make sure to always cancel the interval at the
+ * appropriate moment. See the example below for more details on how and when to do this.
+ * </div>
+ *
+ * @param {function()} fn A function that should be called repeatedly.
+ * @param {number} delay Number of milliseconds between each function call.
+ * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
+ * indefinitely.
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
+ * @returns {promise} A promise which will be notified on each iteration.
+ *
+ * @example
+ * <example module="intervalExample">
+ * <file name="index.html">
+ * <script>
+ * angular.module('intervalExample', [])
+ * .controller('ExampleController', ['$scope', '$interval',
+ * function($scope, $interval) {
+ * $scope.format = 'M/d/yy h:mm:ss a';
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
+ *
+ * var stop;
+ * $scope.fight = function() {
+ * // Don't start a new fight if we are already fighting
+ * if ( angular.isDefined(stop) ) return;
+ *
+ * stop = $interval(function() {
+ * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
+ * $scope.blood_1 = $scope.blood_1 - 3;
+ * $scope.blood_2 = $scope.blood_2 - 4;
+ * } else {
+ * $scope.stopFight();
+ * }
+ * }, 100);
+ * };
+ *
+ * $scope.stopFight = function() {
+ * if (angular.isDefined(stop)) {
+ * $interval.cancel(stop);
+ * stop = undefined;
+ * }
+ * };
+ *
+ * $scope.resetFight = function() {
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
+ * };
+ *
+ * $scope.$on('$destroy', function() {
+ * // Make sure that the interval is destroyed too
+ * $scope.stopFight();
+ * });
+ * }])
+ * // Register the 'myCurrentTime' directive factory method.
+ * // We inject $interval and dateFilter service since the factory method is DI.
+ * .directive('myCurrentTime', ['$interval', 'dateFilter',
+ * function($interval, dateFilter) {
+ * // return the directive link function. (compile function not needed)
+ * return function(scope, element, attrs) {
+ * var format, // date format
+ * stopTime; // so that we can cancel the time updates
+ *
+ * // used to update the UI
+ * function updateTime() {
+ * element.text(dateFilter(new Date(), format));
+ * }
+ *
+ * // watch the expression, and update the UI on change.
+ * scope.$watch(attrs.myCurrentTime, function(value) {
+ * format = value;
+ * updateTime();
+ * });
+ *
+ * stopTime = $interval(updateTime, 1000);
+ *
+ * // listen on DOM destroy (removal) event, and cancel the next UI update
+ * // to prevent updating time after the DOM element was removed.
+ * element.on('$destroy', function() {
+ * $interval.cancel(stopTime);
+ * });
+ * }
+ * }]);
+ * </script>
+ *
+ * <div>
+ * <div ng-controller="ExampleController">
+ * Date format: <input ng-model="format"> <hr/>
+ * Current time is: <span my-current-time="format"></span>
+ * <hr/>
+ * Blood 1 : <font color='red'>{{blood_1}}</font>
+ * Blood 2 : <font color='red'>{{blood_2}}</font>
+ * <button type="button" data-ng-click="fight()">Fight</button>
+ * <button type="button" data-ng-click="stopFight()">StopFight</button>
+ * <button type="button" data-ng-click="resetFight()">resetFight</button>
+ * </div>
+ * </div>
+ *
+ * </file>
+ * </example>
+ */
+ function interval(fn, delay, count, invokeApply) {
+ var setInterval = $window.setInterval,
+ clearInterval = $window.clearInterval,
+ iteration = 0,
+ skipApply = (isDefined(invokeApply) && !invokeApply),
+ deferred = (skipApply ? $$q : $q).defer(),
+ promise = deferred.promise;
+
+ count = isDefined(count) ? count : 0;
+
+ promise.then(null, null, fn);
+
+ promise.$$intervalId = setInterval(function tick() {
+ deferred.notify(iteration++);
+
+ if (count > 0 && iteration >= count) {
+ deferred.resolve(iteration);
+ clearInterval(promise.$$intervalId);
+ delete intervals[promise.$$intervalId];
+ }
+
+ if (!skipApply) $rootScope.$apply();
+
+ }, delay);
+
+ intervals[promise.$$intervalId] = deferred;
+
+ return promise;
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $interval#cancel
+ *
+ * @description
+ * Cancels a task associated with the `promise`.
+ *
+ * @param {promise} promise returned by the `$interval` function.
+ * @returns {boolean} Returns `true` if the task was successfully canceled.
+ */
+ interval.cancel = function(promise) {
+ if (promise && promise.$$intervalId in intervals) {
+ intervals[promise.$$intervalId].reject('canceled');
+ $window.clearInterval(promise.$$intervalId);
+ delete intervals[promise.$$intervalId];
+ return true;
+ }
+ return false;
+ };
+
+ return interval;
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $locale
+ *
+ * @description
+ * $locale service provides localization rules for various Angular components. As of right now the
+ * only public api is:
+ *
+ * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
+ */
+function $LocaleProvider() {
+ this.$get = function() {
+ return {
+ id: 'en-us',
+
+ NUMBER_FORMATS: {
+ DECIMAL_SEP: '.',
+ GROUP_SEP: ',',
+ PATTERNS: [
+ { // Decimal Pattern
+ minInt: 1,
+ minFrac: 0,
+ maxFrac: 3,
+ posPre: '',
+ posSuf: '',
+ negPre: '-',
+ negSuf: '',
+ gSize: 3,
+ lgSize: 3
+ },{ //Currency Pattern
+ minInt: 1,
+ minFrac: 2,
+ maxFrac: 2,
+ posPre: '\u00A4',
+ posSuf: '',
+ negPre: '(\u00A4',
+ negSuf: ')',
+ gSize: 3,
+ lgSize: 3
+ }
+ ],
+ CURRENCY_SYM: '$'
+ },
+
+ DATETIME_FORMATS: {
+ MONTH:
+ 'January,February,March,April,May,June,July,August,September,October,November,December'
+ .split(','),
+ SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
+ DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
+ SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
+ AMPMS: ['AM','PM'],
+ medium: 'MMM d, y h:mm:ss a',
+ 'short': 'M/d/yy h:mm a',
+ fullDate: 'EEEE, MMMM d, y',
+ longDate: 'MMMM d, y',
+ mediumDate: 'MMM d, y',
+ shortDate: 'M/d/yy',
+ mediumTime: 'h:mm:ss a',
+ shortTime: 'h:mm a',
+ ERANAMES: [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ ERAS: [
+ "BC",
+ "AD"
+ ]
+ },
+
+ pluralCat: function(num) {
+ if (num === 1) {
+ return 'one';
+ }
+ return 'other';
+ }
+ };
+ };
+}
+
+var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
+ DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
+var $locationMinErr = minErr('$location');
+
+
+/**
+ * Encode path using encodeUriSegment, ignoring forward slashes
+ *
+ * @param {string} path Path to encode
+ * @returns {string}
+ */
+function encodePath(path) {
+ var segments = path.split('/'),
+ i = segments.length;
+
+ while (i--) {
+ segments[i] = encodeUriSegment(segments[i]);
+ }
+
+ return segments.join('/');
+}
+
+function parseAbsoluteUrl(absoluteUrl, locationObj) {
+ var parsedUrl = urlResolve(absoluteUrl);
+
+ locationObj.$$protocol = parsedUrl.protocol;
+ locationObj.$$host = parsedUrl.hostname;
+ locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
+}
+
+
+function parseAppUrl(relativeUrl, locationObj) {
+ var prefixed = (relativeUrl.charAt(0) !== '/');
+ if (prefixed) {
+ relativeUrl = '/' + relativeUrl;
+ }
+ var match = urlResolve(relativeUrl);
+ locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
+ match.pathname.substring(1) : match.pathname);
+ locationObj.$$search = parseKeyValue(match.search);
+ locationObj.$$hash = decodeURIComponent(match.hash);
+
+ // make sure path starts with '/';
+ if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
+ locationObj.$$path = '/' + locationObj.$$path;
+ }
+}
+
+
+/**
+ *
+ * @param {string} begin
+ * @param {string} whole
+ * @returns {string} returns text from whole after begin or undefined if it does not begin with
+ * expected string.
+ */
+function beginsWith(begin, whole) {
+ if (whole.indexOf(begin) === 0) {
+ return whole.substr(begin.length);
+ }
+}
+
+
+function stripHash(url) {
+ var index = url.indexOf('#');
+ return index == -1 ? url : url.substr(0, index);
+}
+
+function trimEmptyHash(url) {
+ return url.replace(/(#.+)|#$/, '$1');
+}
+
+
+function stripFile(url) {
+ return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
+}
+
+/* return the server only (scheme://host:port) */
+function serverBase(url) {
+ return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
+}
+
+
+/**
+ * LocationHtml5Url represents an url
+ * This object is exposed as $location service when HTML5 mode is enabled and supported
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} basePrefix url path prefix
+ */
+function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
+ this.$$html5 = true;
+ basePrefix = basePrefix || '';
+ parseAbsoluteUrl(appBase, this);
+
+
+ /**
+ * Parse given html5 (regular) url string into properties
+ * @param {string} url HTML5 url
+ * @private
+ */
+ this.$$parse = function(url) {
+ var pathUrl = beginsWith(appBaseNoFile, url);
+ if (!isString(pathUrl)) {
+ throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
+ appBaseNoFile);
+ }
+
+ parseAppUrl(pathUrl, this);
+
+ if (!this.$$path) {
+ this.$$path = '/';
+ }
+
+ this.$$compose();
+ };
+
+ /**
+ * Compose url and update `absUrl` property
+ * @private
+ */
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
+ };
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (relHref && relHref[0] === '#') {
+ // special case for links to hash fragments:
+ // keep the old url and only replace the hash fragment
+ this.hash(relHref.slice(1));
+ return true;
+ }
+ var appUrl, prevAppUrl;
+ var rewrittenUrl;
+
+ if ((appUrl = beginsWith(appBase, url)) !== undefined) {
+ prevAppUrl = appUrl;
+ if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {
+ rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
+ } else {
+ rewrittenUrl = appBase + prevAppUrl;
+ }
+ } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {
+ rewrittenUrl = appBaseNoFile + appUrl;
+ } else if (appBaseNoFile == url + '/') {
+ rewrittenUrl = appBaseNoFile;
+ }
+ if (rewrittenUrl) {
+ this.$$parse(rewrittenUrl);
+ }
+ return !!rewrittenUrl;
+ };
+}
+
+
+/**
+ * LocationHashbangUrl represents url
+ * This object is exposed as $location service when developer doesn't opt into html5 mode.
+ * It also serves as the base class for html5 mode fallback on legacy browsers.
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} hashPrefix hashbang prefix
+ */
+function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
+
+ parseAbsoluteUrl(appBase, this);
+
+
+ /**
+ * Parse given hashbang url into properties
+ * @param {string} url Hashbang url
+ * @private
+ */
+ this.$$parse = function(url) {
+ var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
+ var withoutHashUrl;
+
+ if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
+
+ // The rest of the url starts with a hash so we have
+ // got either a hashbang path or a plain hash fragment
+ withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
+ if (isUndefined(withoutHashUrl)) {
+ // There was no hashbang prefix so we just have a hash fragment
+ withoutHashUrl = withoutBaseUrl;
+ }
+
+ } else {
+ // There was no hashbang path nor hash fragment:
+ // If we are in HTML5 mode we use what is left as the path;
+ // Otherwise we ignore what is left
+ if (this.$$html5) {
+ withoutHashUrl = withoutBaseUrl;
+ } else {
+ withoutHashUrl = '';
+ if (isUndefined(withoutBaseUrl)) {
+ appBase = url;
+ this.replace();
+ }
+ }
+ }
+
+ parseAppUrl(withoutHashUrl, this);
+
+ this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
+
+ this.$$compose();
+
+ /*
+ * In Windows, on an anchor node on documents loaded from
+ * the filesystem, the browser will return a pathname
+ * prefixed with the drive name ('/C:/path') when a
+ * pathname without a drive is set:
+ * * a.setAttribute('href', '/foo')
+ * * a.pathname === '/C:/foo' //true
+ *
+ * Inside of Angular, we're always using pathnames that
+ * do not include drive names for routing.
+ */
+ function removeWindowsDriveName(path, url, base) {
+ /*
+ Matches paths for file protocol on windows,
+ such as /C:/foo/bar, and captures only /foo/bar.
+ */
+ var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
+
+ var firstPathSegmentMatch;
+
+ //Get the relative path from the input URL.
+ if (url.indexOf(base) === 0) {
+ url = url.replace(base, '');
+ }
+
+ // The input URL intentionally contains a first path segment that ends with a colon.
+ if (windowsFilePathExp.exec(url)) {
+ return path;
+ }
+
+ firstPathSegmentMatch = windowsFilePathExp.exec(path);
+ return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
+ }
+ };
+
+ /**
+ * Compose hashbang url and update `absUrl` property
+ * @private
+ */
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
+ };
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (stripHash(appBase) == stripHash(url)) {
+ this.$$parse(url);
+ return true;
+ }
+ return false;
+ };
+}
+
+
+/**
+ * LocationHashbangUrl represents url
+ * This object is exposed as $location service when html5 history api is enabled but the browser
+ * does not support it.
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} hashPrefix hashbang prefix
+ */
+function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
+ this.$$html5 = true;
+ LocationHashbangUrl.apply(this, arguments);
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (relHref && relHref[0] === '#') {
+ // special case for links to hash fragments:
+ // keep the old url and only replace the hash fragment
+ this.hash(relHref.slice(1));
+ return true;
+ }
+
+ var rewrittenUrl;
+ var appUrl;
+
+ if (appBase == stripHash(url)) {
+ rewrittenUrl = url;
+ } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
+ rewrittenUrl = appBase + hashPrefix + appUrl;
+ } else if (appBaseNoFile === url + '/') {
+ rewrittenUrl = appBaseNoFile;
+ }
+ if (rewrittenUrl) {
+ this.$$parse(rewrittenUrl);
+ }
+ return !!rewrittenUrl;
+ };
+
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'
+ this.$$absUrl = appBase + hashPrefix + this.$$url;
+ };
+
+}
+
+
+var locationPrototype = {
+
+ /**
+ * Are we in html5 mode?
+ * @private
+ */
+ $$html5: false,
+
+ /**
+ * Has any change been replacing?
+ * @private
+ */
+ $$replace: false,
+
+ /**
+ * @ngdoc method
+ * @name $location#absUrl
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return full url representation with all segments encoded according to rules specified in
+ * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var absUrl = $location.absUrl();
+ * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
+ * ```
+ *
+ * @return {string} full url
+ */
+ absUrl: locationGetter('$$absUrl'),
+
+ /**
+ * @ngdoc method
+ * @name $location#url
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
+ *
+ * Change path, search and hash, when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var url = $location.url();
+ * // => "/some/path?foo=bar&baz=xoxo"
+ * ```
+ *
+ * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
+ * @return {string} url
+ */
+ url: function(url) {
+ if (isUndefined(url))
+ return this.$$url;
+
+ var match = PATH_MATCH.exec(url);
+ if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
+ if (match[2] || match[1] || url === '') this.search(match[3] || '');
+ this.hash(match[5] || '');
+
+ return this;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $location#protocol
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return protocol of current url.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var protocol = $location.protocol();
+ * // => "http"
+ * ```
+ *
+ * @return {string} protocol of current url
+ */
+ protocol: locationGetter('$$protocol'),
+
+ /**
+ * @ngdoc method
+ * @name $location#host
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return host of current url.
+ *
+ * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var host = $location.host();
+ * // => "example.com"
+ *
+ * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
+ * host = $location.host();
+ * // => "example.com"
+ * host = location.host;
+ * // => "example.com:8080"
+ * ```
+ *
+ * @return {string} host of current url.
+ */
+ host: locationGetter('$$host'),
+
+ /**
+ * @ngdoc method
+ * @name $location#port
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return port of current url.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var port = $location.port();
+ * // => 80
+ * ```
+ *
+ * @return {Number} port
+ */
+ port: locationGetter('$$port'),
+
+ /**
+ * @ngdoc method
+ * @name $location#path
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return path of current url when called without any parameter.
+ *
+ * Change path when called with parameter and return `$location`.
+ *
+ * Note: Path should always begin with forward slash (/), this method will add the forward slash
+ * if it is missing.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var path = $location.path();
+ * // => "/some/path"
+ * ```
+ *
+ * @param {(string|number)=} path New path
+ * @return {string} path
+ */
+ path: locationGetterSetter('$$path', function(path) {
+ path = path !== null ? path.toString() : '';
+ return path.charAt(0) == '/' ? path : '/' + path;
+ }),
+
+ /**
+ * @ngdoc method
+ * @name $location#search
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return search part (as object) of current url when called without any parameter.
+ *
+ * Change search part when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var searchObject = $location.search();
+ * // => {foo: 'bar', baz: 'xoxo'}
+ *
+ * // set foo to 'yipee'
+ * $location.search('foo', 'yipee');
+ * // $location.search() => {foo: 'yipee', baz: 'xoxo'}
+ * ```
+ *
+ * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
+ * hash object.
+ *
+ * When called with a single argument the method acts as a setter, setting the `search` component
+ * of `$location` to the specified value.
+ *
+ * If the argument is a hash object containing an array of values, these values will be encoded
+ * as duplicate search parameters in the url.
+ *
+ * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
+ * will override only a single search property.
+ *
+ * If `paramValue` is an array, it will override the property of the `search` component of
+ * `$location` specified via the first argument.
+ *
+ * If `paramValue` is `null`, the property specified via the first argument will be deleted.
+ *
+ * If `paramValue` is `true`, the property specified via the first argument will be added with no
+ * value nor trailing equal sign.
+ *
+ * @return {Object} If called with no arguments returns the parsed `search` object. If called with
+ * one or more arguments returns `$location` object itself.
+ */
+ search: function(search, paramValue) {
+ switch (arguments.length) {
+ case 0:
+ return this.$$search;
+ case 1:
+ if (isString(search) || isNumber(search)) {
+ search = search.toString();
+ this.$$search = parseKeyValue(search);
+ } else if (isObject(search)) {
+ search = copy(search, {});
+ // remove object undefined or null properties
+ forEach(search, function(value, key) {
+ if (value == null) delete search[key];
+ });
+
+ this.$$search = search;
+ } else {
+ throw $locationMinErr('isrcharg',
+ 'The first argument of the `$location#search()` call must be a string or an object.');
+ }
+ break;
+ default:
+ if (isUndefined(paramValue) || paramValue === null) {
+ delete this.$$search[search];
+ } else {
+ this.$$search[search] = paramValue;
+ }
+ }
+
+ this.$$compose();
+ return this;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $location#hash
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return hash fragment when called without any parameter.
+ *
+ * Change hash fragment when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
+ * var hash = $location.hash();
+ * // => "hashValue"
+ * ```
+ *
+ * @param {(string|number)=} hash New hash fragment
+ * @return {string} hash
+ */
+ hash: locationGetterSetter('$$hash', function(hash) {
+ return hash !== null ? hash.toString() : '';
+ }),
+
+ /**
+ * @ngdoc method
+ * @name $location#replace
+ *
+ * @description
+ * If called, all changes to $location during current `$digest` will be replacing current history
+ * record, instead of adding new one.
+ */
+ replace: function() {
+ this.$$replace = true;
+ return this;
+ }
+};
+
+forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
+ Location.prototype = Object.create(locationPrototype);
+
+ /**
+ * @ngdoc method
+ * @name $location#state
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return the history state object when called without any parameter.
+ *
+ * Change the history state object when called with one parameter and return `$location`.
+ * The state object is later passed to `pushState` or `replaceState`.
+ *
+ * NOTE: This method is supported only in HTML5 mode and only in browsers supporting
+ * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support
+ * older browsers (like IE9 or Android < 4.0), don't use this method.
+ *
+ * @param {object=} state State object for pushState or replaceState
+ * @return {object} state
+ */
+ Location.prototype.state = function(state) {
+ if (!arguments.length)
+ return this.$$state;
+
+ if (Location !== LocationHtml5Url || !this.$$html5) {
+ throw $locationMinErr('nostate', 'History API state support is available only ' +
+ 'in HTML5 mode and only in browsers supporting HTML5 History API');
+ }
+ // The user might modify `stateObject` after invoking `$location.state(stateObject)`
+ // but we're changing the $$state reference to $browser.state() during the $digest
+ // so the modification window is narrow.
+ this.$$state = isUndefined(state) ? null : state;
+
+ return this;
+ };
+});
+
+
+function locationGetter(property) {
+ return function() {
+ return this[property];
+ };
+}
+
+
+function locationGetterSetter(property, preprocess) {
+ return function(value) {
+ if (isUndefined(value))
+ return this[property];
+
+ this[property] = preprocess(value);
+ this.$$compose();
+
+ return this;
+ };
+}
+
+
+/**
+ * @ngdoc service
+ * @name $location
+ *
+ * @requires $rootElement
+ *
+ * @description
+ * The $location service parses the URL in the browser address bar (based on the
+ * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
+ * available to your application. Changes to the URL in the address bar are reflected into
+ * $location service and changes to $location are reflected into the browser address bar.
+ *
+ * **The $location service:**
+ *
+ * - Exposes the current URL in the browser address bar, so you can
+ * - Watch and observe the URL.
+ * - Change the URL.
+ * - Synchronizes the URL with the browser when the user
+ * - Changes the address bar.
+ * - Clicks the back or forward button (or clicks a History link).
+ * - Clicks on a link.
+ * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
+ *
+ * For more information see {@link guide/$location Developer Guide: Using $location}
+ */
+
+/**
+ * @ngdoc provider
+ * @name $locationProvider
+ * @description
+ * Use the `$locationProvider` to configure how the application deep linking paths are stored.
+ */
+function $LocationProvider() {
+ var hashPrefix = '',
+ html5Mode = {
+ enabled: false,
+ requireBase: true,
+ rewriteLinks: true
+ };
+
+ /**
+ * @ngdoc method
+ * @name $locationProvider#hashPrefix
+ * @description
+ * @param {string=} prefix Prefix for hash part (containing path and search)
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ */
+ this.hashPrefix = function(prefix) {
+ if (isDefined(prefix)) {
+ hashPrefix = prefix;
+ return this;
+ } else {
+ return hashPrefix;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $locationProvider#html5Mode
+ * @description
+ * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
+ * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
+ * properties:
+ * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
+ * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
+ * support `pushState`.
+ * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
+ * whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
+ * true, and a base tag is not present, an error will be thrown when `$location` is injected.
+ * See the {@link guide/$location $location guide for more information}
+ * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
+ * enables/disables url rewriting for relative links.
+ *
+ * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
+ */
+ this.html5Mode = function(mode) {
+ if (isBoolean(mode)) {
+ html5Mode.enabled = mode;
+ return this;
+ } else if (isObject(mode)) {
+
+ if (isBoolean(mode.enabled)) {
+ html5Mode.enabled = mode.enabled;
+ }
+
+ if (isBoolean(mode.requireBase)) {
+ html5Mode.requireBase = mode.requireBase;
+ }
+
+ if (isBoolean(mode.rewriteLinks)) {
+ html5Mode.rewriteLinks = mode.rewriteLinks;
+ }
+
+ return this;
+ } else {
+ return html5Mode;
+ }
+ };
+
+ /**
+ * @ngdoc event
+ * @name $location#$locationChangeStart
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted before a URL will change.
+ *
+ * This change can be prevented by calling
+ * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
+ * details about event object. Upon successful change
+ * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
+ *
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
+ * the browser supports the HTML5 History API.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {string} newUrl New URL
+ * @param {string=} oldUrl URL that was before it was changed.
+ * @param {string=} newState New history state object
+ * @param {string=} oldState History state object that was before it was changed.
+ */
+
+ /**
+ * @ngdoc event
+ * @name $location#$locationChangeSuccess
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted after a URL was changed.
+ *
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
+ * the browser supports the HTML5 History API.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {string} newUrl New URL
+ * @param {string=} oldUrl URL that was before it was changed.
+ * @param {string=} newState New history state object
+ * @param {string=} oldState History state object that was before it was changed.
+ */
+
+ this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
+ function($rootScope, $browser, $sniffer, $rootElement, $window) {
+ var $location,
+ LocationMode,
+ baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
+ initialUrl = $browser.url(),
+ appBase;
+
+ if (html5Mode.enabled) {
+ if (!baseHref && html5Mode.requireBase) {
+ throw $locationMinErr('nobase',
+ "$location in HTML5 mode requires a <base> tag to be present!");
+ }
+ appBase = serverBase(initialUrl) + (baseHref || '/');
+ LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
+ } else {
+ appBase = stripHash(initialUrl);
+ LocationMode = LocationHashbangUrl;
+ }
+ var appBaseNoFile = stripFile(appBase);
+
+ $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
+ $location.$$parseLinkUrl(initialUrl, initialUrl);
+
+ $location.$$state = $browser.state();
+
+ var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
+
+ function setBrowserUrlWithFallback(url, replace, state) {
+ var oldUrl = $location.url();
+ var oldState = $location.$$state;
+ try {
+ $browser.url(url, replace, state);
+
+ // Make sure $location.state() returns referentially identical (not just deeply equal)
+ // state object; this makes possible quick checking if the state changed in the digest
+ // loop. Checking deep equality would be too expensive.
+ $location.$$state = $browser.state();
+ } catch (e) {
+ // Restore old values if pushState fails
+ $location.url(oldUrl);
+ $location.$$state = oldState;
+
+ throw e;
+ }
+ }
+
+ $rootElement.on('click', function(event) {
+ // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
+ // currently we open nice url link and redirect then
+
+ if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;
+
+ var elm = jqLite(event.target);
+
+ // traverse the DOM up to find first A tag
+ while (nodeName_(elm[0]) !== 'a') {
+ // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
+ if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
+ }
+
+ var absHref = elm.prop('href');
+ // get the actual href attribute - see
+ // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
+ var relHref = elm.attr('href') || elm.attr('xlink:href');
+
+ if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
+ // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
+ // an animation.
+ absHref = urlResolve(absHref.animVal).href;
+ }
+
+ // Ignore when url is started with javascript: or mailto:
+ if (IGNORE_URI_REGEXP.test(absHref)) return;
+
+ if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
+ if ($location.$$parseLinkUrl(absHref, relHref)) {
+ // We do a preventDefault for all urls that are part of the angular application,
+ // in html5mode and also without, so that we are able to abort navigation without
+ // getting double entries in the location history.
+ event.preventDefault();
+ // update location manually
+ if ($location.absUrl() != $browser.url()) {
+ $rootScope.$apply();
+ // hack to work around FF6 bug 684208 when scenario runner clicks on links
+ $window.angular['ff-684208-preventDefault'] = true;
+ }
+ }
+ }
+ });
+
+
+ // rewrite hashbang url <> html5 url
+ if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
+ $browser.url($location.absUrl(), true);
+ }
+
+ var initializing = true;
+
+ // update $location when $browser url changes
+ $browser.onUrlChange(function(newUrl, newState) {
+
+ if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
+ // If we are navigating outside of the app then force a reload
+ $window.location.href = newUrl;
+ return;
+ }
+
+ $rootScope.$evalAsync(function() {
+ var oldUrl = $location.absUrl();
+ var oldState = $location.$$state;
+ var defaultPrevented;
+
+ $location.$$parse(newUrl);
+ $location.$$state = newState;
+
+ defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ newState, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
+ $location.$$parse(oldUrl);
+ $location.$$state = oldState;
+ setBrowserUrlWithFallback(oldUrl, false, oldState);
+ } else {
+ initializing = false;
+ afterLocationChange(oldUrl, oldState);
+ }
+ });
+ if (!$rootScope.$$phase) $rootScope.$digest();
+ });
+
+ // update browser
+ $rootScope.$watch(function $locationWatch() {
+ var oldUrl = trimEmptyHash($browser.url());
+ var newUrl = trimEmptyHash($location.absUrl());
+ var oldState = $browser.state();
+ var currentReplace = $location.$$replace;
+ var urlOrStateChanged = oldUrl !== newUrl ||
+ ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
+
+ if (initializing || urlOrStateChanged) {
+ initializing = false;
+
+ $rootScope.$evalAsync(function() {
+ var newUrl = $location.absUrl();
+ var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ $location.$$state, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
+ $location.$$parse(oldUrl);
+ $location.$$state = oldState;
+ } else {
+ if (urlOrStateChanged) {
+ setBrowserUrlWithFallback(newUrl, currentReplace,
+ oldState === $location.$$state ? null : $location.$$state);
+ }
+ afterLocationChange(oldUrl, oldState);
+ }
+ });
+ }
+
+ $location.$$replace = false;
+
+ // we don't need to return anything because $evalAsync will make the digest loop dirty when
+ // there is a change
+ });
+
+ return $location;
+
+ function afterLocationChange(oldUrl, oldState) {
+ $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,
+ $location.$$state, oldState);
+ }
+}];
+}
+
+/**
+ * @ngdoc service
+ * @name $log
+ * @requires $window
+ *
+ * @description
+ * Simple service for logging. Default implementation safely writes the message
+ * into the browser's console (if present).
+ *
+ * The main purpose of this service is to simplify debugging and troubleshooting.
+ *
+ * The default is to log `debug` messages. You can use
+ * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
+ *
+ * @example
+ <example module="logExample">
+ <file name="script.js">
+ angular.module('logExample', [])
+ .controller('LogController', ['$scope', '$log', function($scope, $log) {
+ $scope.$log = $log;
+ $scope.message = 'Hello World!';
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="LogController">
+ <p>Reload this page with open console, enter text and hit the log button...</p>
+ Message:
+ <input type="text" ng-model="message"/>
+ <button ng-click="$log.log(message)">log</button>
+ <button ng-click="$log.warn(message)">warn</button>
+ <button ng-click="$log.info(message)">info</button>
+ <button ng-click="$log.error(message)">error</button>
+ <button ng-click="$log.debug(message)">debug</button>
+ </div>
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc provider
+ * @name $logProvider
+ * @description
+ * Use the `$logProvider` to configure how the application logs messages
+ */
+function $LogProvider() {
+ var debug = true,
+ self = this;
+
+ /**
+ * @ngdoc method
+ * @name $logProvider#debugEnabled
+ * @description
+ * @param {boolean=} flag enable or disable debug level messages
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ */
+ this.debugEnabled = function(flag) {
+ if (isDefined(flag)) {
+ debug = flag;
+ return this;
+ } else {
+ return debug;
+ }
+ };
+
+ this.$get = ['$window', function($window) {
+ return {
+ /**
+ * @ngdoc method
+ * @name $log#log
+ *
+ * @description
+ * Write a log message
+ */
+ log: consoleLog('log'),
+
+ /**
+ * @ngdoc method
+ * @name $log#info
+ *
+ * @description
+ * Write an information message
+ */
+ info: consoleLog('info'),
+
+ /**
+ * @ngdoc method
+ * @name $log#warn
+ *
+ * @description
+ * Write a warning message
+ */
+ warn: consoleLog('warn'),
+
+ /**
+ * @ngdoc method
+ * @name $log#error
+ *
+ * @description
+ * Write an error message
+ */
+ error: consoleLog('error'),
+
+ /**
+ * @ngdoc method
+ * @name $log#debug
+ *
+ * @description
+ * Write a debug message
+ */
+ debug: (function() {
+ var fn = consoleLog('debug');
+
+ return function() {
+ if (debug) {
+ fn.apply(self, arguments);
+ }
+ };
+ }())
+ };
+
+ function formatError(arg) {
+ if (arg instanceof Error) {
+ if (arg.stack) {
+ arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
+ ? 'Error: ' + arg.message + '\n' + arg.stack
+ : arg.stack;
+ } else if (arg.sourceURL) {
+ arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
+ }
+ }
+ return arg;
+ }
+
+ function consoleLog(type) {
+ var console = $window.console || {},
+ logFn = console[type] || console.log || noop,
+ hasApply = false;
+
+ // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
+ // The reason behind this is that console.log has type "object" in IE8...
+ try {
+ hasApply = !!logFn.apply;
+ } catch (e) {}
+
+ if (hasApply) {
+ return function() {
+ var args = [];
+ forEach(arguments, function(arg) {
+ args.push(formatError(arg));
+ });
+ return logFn.apply(console, args);
+ };
+ }
+
+ // we are IE which either doesn't have window.console => this is noop and we do nothing,
+ // or we are IE where console.log doesn't have apply so we log at least first 2 args
+ return function(arg1, arg2) {
+ logFn(arg1, arg2 == null ? '' : arg2);
+ };
+ }
+ }];
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $parseMinErr = minErr('$parse');
+
+// Sandboxing Angular Expressions
+// ------------------------------
+// Angular expressions are generally considered safe because these expressions only have direct
+// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
+// obtaining a reference to native JS functions such as the Function constructor.
+//
+// As an example, consider the following Angular expression:
+//
+// {}.toString.constructor('alert("evil JS code")')
+//
+// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
+// against the expression language, but not to prevent exploits that were enabled by exposing
+// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
+// practice and therefore we are not even trying to protect against interaction with an object
+// explicitly exposed in this way.
+//
+// In general, it is not possible to access a Window object from an angular expression unless a
+// window or some DOM object that has a reference to window is published onto a Scope.
+// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
+// native objects.
+//
+// See https://docs.angularjs.org/guide/security
+
+
+function ensureSafeMemberName(name, fullExpression) {
+ if (name === "__defineGetter__" || name === "__defineSetter__"
+ || name === "__lookupGetter__" || name === "__lookupSetter__"
+ || name === "__proto__") {
+ throw $parseMinErr('isecfld',
+ 'Attempting to access a disallowed field in Angular expressions! '
+ + 'Expression: {0}', fullExpression);
+ }
+ return name;
+}
+
+function getStringValue(name, fullExpression) {
+ // From the JavaScript docs:
+ // Property names must be strings. This means that non-string objects cannot be used
+ // as keys in an object. Any non-string object, including a number, is typecasted
+ // into a string via the toString method.
+ //
+ // So, to ensure that we are checking the same `name` that JavaScript would use,
+ // we cast it to a string, if possible.
+ // Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
+ // this is, this will handle objects that misbehave.
+ name = name + '';
+ if (!isString(name)) {
+ throw $parseMinErr('iseccst',
+ 'Cannot convert object to primitive value! '
+ + 'Expression: {0}', fullExpression);
+ }
+ return name;
+}
+
+function ensureSafeObject(obj, fullExpression) {
+ // nifty check if obj is Function that is fast and works across iframes and other contexts
+ if (obj) {
+ if (obj.constructor === obj) {
+ throw $parseMinErr('isecfn',
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// isWindow(obj)
+ obj.window === obj) {
+ throw $parseMinErr('isecwindow',
+ 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// isElement(obj)
+ obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
+ throw $parseMinErr('isecdom',
+ 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// block Object so that we can't get hold of dangerous Object.* methods
+ obj === Object) {
+ throw $parseMinErr('isecobj',
+ 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ }
+ }
+ return obj;
+}
+
+var CALL = Function.prototype.call;
+var APPLY = Function.prototype.apply;
+var BIND = Function.prototype.bind;
+
+function ensureSafeFunction(obj, fullExpression) {
+ if (obj) {
+ if (obj.constructor === obj) {
+ throw $parseMinErr('isecfn',
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (obj === CALL || obj === APPLY || obj === BIND) {
+ throw $parseMinErr('isecff',
+ 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ }
+ }
+}
+
+//Keyword constants
+var CONSTANTS = createMap();
+forEach({
+ 'null': function() { return null; },
+ 'true': function() { return true; },
+ 'false': function() { return false; },
+ 'undefined': function() {}
+}, function(constantGetter, name) {
+ constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;
+ CONSTANTS[name] = constantGetter;
+});
+
+//Not quite a constant, but can be lex/parsed the same
+CONSTANTS['this'] = function(self) { return self; };
+CONSTANTS['this'].sharedGetter = true;
+
+
+//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
+var OPERATORS = extend(createMap(), {
+ '+':function(self, locals, a, b) {
+ a=a(self, locals); b=b(self, locals);
+ if (isDefined(a)) {
+ if (isDefined(b)) {
+ return a + b;
+ }
+ return a;
+ }
+ return isDefined(b) ? b : undefined;},
+ '-':function(self, locals, a, b) {
+ a=a(self, locals); b=b(self, locals);
+ return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);
+ },
+ '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},
+ '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},
+ '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},
+ '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},
+ '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},
+ '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},
+ '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},
+ '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},
+ '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},
+ '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},
+ '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},
+ '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},
+ '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},
+ '!':function(self, locals, a) {return !a(self, locals);},
+
+ //Tokenized as operators but parsed as assignment/filters
+ '=':true,
+ '|':true
+});
+var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
+
+
+/////////////////////////////////////////
+
+
+/**
+ * @constructor
+ */
+var Lexer = function(options) {
+ this.options = options;
+};
+
+Lexer.prototype = {
+ constructor: Lexer,
+
+ lex: function(text) {
+ this.text = text;
+ this.index = 0;
+ this.tokens = [];
+
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ if (ch === '"' || ch === "'") {
+ this.readString(ch);
+ } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
+ this.readNumber();
+ } else if (this.isIdent(ch)) {
+ this.readIdent();
+ } else if (this.is(ch, '(){}[].,;:?')) {
+ this.tokens.push({index: this.index, text: ch});
+ this.index++;
+ } else if (this.isWhitespace(ch)) {
+ this.index++;
+ } else {
+ var ch2 = ch + this.peek();
+ var ch3 = ch2 + this.peek(2);
+ var op1 = OPERATORS[ch];
+ var op2 = OPERATORS[ch2];
+ var op3 = OPERATORS[ch3];
+ if (op1 || op2 || op3) {
+ var token = op3 ? ch3 : (op2 ? ch2 : ch);
+ this.tokens.push({index: this.index, text: token, operator: true});
+ this.index += token.length;
+ } else {
+ this.throwError('Unexpected next character ', this.index, this.index + 1);
+ }
+ }
+ }
+ return this.tokens;
+ },
+
+ is: function(ch, chars) {
+ return chars.indexOf(ch) !== -1;
+ },
+
+ peek: function(i) {
+ var num = i || 1;
+ return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
+ },
+
+ isNumber: function(ch) {
+ return ('0' <= ch && ch <= '9') && typeof ch === "string";
+ },
+
+ isWhitespace: function(ch) {
+ // IE treats non-breaking space as \u00A0
+ return (ch === ' ' || ch === '\r' || ch === '\t' ||
+ ch === '\n' || ch === '\v' || ch === '\u00A0');
+ },
+
+ isIdent: function(ch) {
+ return ('a' <= ch && ch <= 'z' ||
+ 'A' <= ch && ch <= 'Z' ||
+ '_' === ch || ch === '$');
+ },
+
+ isExpOperator: function(ch) {
+ return (ch === '-' || ch === '+' || this.isNumber(ch));
+ },
+
+ throwError: function(error, start, end) {
+ end = end || this.index;
+ var colStr = (isDefined(start)
+ ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'
+ : ' ' + end);
+ throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
+ error, colStr, this.text);
+ },
+
+ readNumber: function() {
+ var number = '';
+ var start = this.index;
+ while (this.index < this.text.length) {
+ var ch = lowercase(this.text.charAt(this.index));
+ if (ch == '.' || this.isNumber(ch)) {
+ number += ch;
+ } else {
+ var peekCh = this.peek();
+ if (ch == 'e' && this.isExpOperator(peekCh)) {
+ number += ch;
+ } else if (this.isExpOperator(ch) &&
+ peekCh && this.isNumber(peekCh) &&
+ number.charAt(number.length - 1) == 'e') {
+ number += ch;
+ } else if (this.isExpOperator(ch) &&
+ (!peekCh || !this.isNumber(peekCh)) &&
+ number.charAt(number.length - 1) == 'e') {
+ this.throwError('Invalid exponent');
+ } else {
+ break;
+ }
+ }
+ this.index++;
+ }
+ this.tokens.push({
+ index: start,
+ text: number,
+ constant: true,
+ value: Number(number)
+ });
+ },
+
+ readIdent: function() {
+ var start = this.index;
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ if (!(this.isIdent(ch) || this.isNumber(ch))) {
+ break;
+ }
+ this.index++;
+ }
+ this.tokens.push({
+ index: start,
+ text: this.text.slice(start, this.index),
+ identifier: true
+ });
+ },
+
+ readString: function(quote) {
+ var start = this.index;
+ this.index++;
+ var string = '';
+ var rawString = quote;
+ var escape = false;
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ rawString += ch;
+ if (escape) {
+ if (ch === 'u') {
+ var hex = this.text.substring(this.index + 1, this.index + 5);
+ if (!hex.match(/[\da-f]{4}/i))
+ this.throwError('Invalid unicode escape [\\u' + hex + ']');
+ this.index += 4;
+ string += String.fromCharCode(parseInt(hex, 16));
+ } else {
+ var rep = ESCAPE[ch];
+ string = string + (rep || ch);
+ }
+ escape = false;
+ } else if (ch === '\\') {
+ escape = true;
+ } else if (ch === quote) {
+ this.index++;
+ this.tokens.push({
+ index: start,
+ text: rawString,
+ constant: true,
+ value: string
+ });
+ return;
+ } else {
+ string += ch;
+ }
+ this.index++;
+ }
+ this.throwError('Unterminated quote', start);
+ }
+};
+
+
+function isConstant(exp) {
+ return exp.constant;
+}
+
+/**
+ * @constructor
+ */
+var Parser = function(lexer, $filter, options) {
+ this.lexer = lexer;
+ this.$filter = $filter;
+ this.options = options;
+};
+
+Parser.ZERO = extend(function() {
+ return 0;
+}, {
+ sharedGetter: true,
+ constant: true
+});
+
+Parser.prototype = {
+ constructor: Parser,
+
+ parse: function(text) {
+ this.text = text;
+ this.tokens = this.lexer.lex(text);
+
+ var value = this.statements();
+
+ if (this.tokens.length !== 0) {
+ this.throwError('is an unexpected token', this.tokens[0]);
+ }
+
+ value.literal = !!value.literal;
+ value.constant = !!value.constant;
+
+ return value;
+ },
+
+ primary: function() {
+ var primary;
+ if (this.expect('(')) {
+ primary = this.filterChain();
+ this.consume(')');
+ } else if (this.expect('[')) {
+ primary = this.arrayDeclaration();
+ } else if (this.expect('{')) {
+ primary = this.object();
+ } else if (this.peek().identifier && this.peek().text in CONSTANTS) {
+ primary = CONSTANTS[this.consume().text];
+ } else if (this.peek().identifier) {
+ primary = this.identifier();
+ } else if (this.peek().constant) {
+ primary = this.constant();
+ } else {
+ this.throwError('not a primary expression', this.peek());
+ }
+
+ var next, context;
+ while ((next = this.expect('(', '[', '.'))) {
+ if (next.text === '(') {
+ primary = this.functionCall(primary, context);
+ context = null;
+ } else if (next.text === '[') {
+ context = primary;
+ primary = this.objectIndex(primary);
+ } else if (next.text === '.') {
+ context = primary;
+ primary = this.fieldAccess(primary);
+ } else {
+ this.throwError('IMPOSSIBLE');
+ }
+ }
+ return primary;
+ },
+
+ throwError: function(msg, token) {
+ throw $parseMinErr('syntax',
+ 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
+ token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
+ },
+
+ peekToken: function() {
+ if (this.tokens.length === 0)
+ throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
+ return this.tokens[0];
+ },
+
+ peek: function(e1, e2, e3, e4) {
+ return this.peekAhead(0, e1, e2, e3, e4);
+ },
+ peekAhead: function(i, e1, e2, e3, e4) {
+ if (this.tokens.length > i) {
+ var token = this.tokens[i];
+ var t = token.text;
+ if (t === e1 || t === e2 || t === e3 || t === e4 ||
+ (!e1 && !e2 && !e3 && !e4)) {
+ return token;
+ }
+ }
+ return false;
+ },
+
+ expect: function(e1, e2, e3, e4) {
+ var token = this.peek(e1, e2, e3, e4);
+ if (token) {
+ this.tokens.shift();
+ return token;
+ }
+ return false;
+ },
+
+ consume: function(e1) {
+ if (this.tokens.length === 0) {
+ throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
+ }
+
+ var token = this.expect(e1);
+ if (!token) {
+ this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
+ }
+ return token;
+ },
+
+ unaryFn: function(op, right) {
+ var fn = OPERATORS[op];
+ return extend(function $parseUnaryFn(self, locals) {
+ return fn(self, locals, right);
+ }, {
+ constant:right.constant,
+ inputs: [right]
+ });
+ },
+
+ binaryFn: function(left, op, right, isBranching) {
+ var fn = OPERATORS[op];
+ return extend(function $parseBinaryFn(self, locals) {
+ return fn(self, locals, left, right);
+ }, {
+ constant: left.constant && right.constant,
+ inputs: !isBranching && [left, right]
+ });
+ },
+
+ identifier: function() {
+ var id = this.consume().text;
+
+ //Continue reading each `.identifier` unless it is a method invocation
+ while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {
+ id += this.consume().text + this.consume().text;
+ }
+
+ return getterFn(id, this.options, this.text);
+ },
+
+ constant: function() {
+ var value = this.consume().value;
+
+ return extend(function $parseConstant() {
+ return value;
+ }, {
+ constant: true,
+ literal: true
+ });
+ },
+
+ statements: function() {
+ var statements = [];
+ while (true) {
+ if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
+ statements.push(this.filterChain());
+ if (!this.expect(';')) {
+ // optimize for the common case where there is only one statement.
+ // TODO(size): maybe we should not support multiple statements?
+ return (statements.length === 1)
+ ? statements[0]
+ : function $parseStatements(self, locals) {
+ var value;
+ for (var i = 0, ii = statements.length; i < ii; i++) {
+ value = statements[i](self, locals);
+ }
+ return value;
+ };
+ }
+ }
+ },
+
+ filterChain: function() {
+ var left = this.expression();
+ var token;
+ while ((token = this.expect('|'))) {
+ left = this.filter(left);
+ }
+ return left;
+ },
+
+ filter: function(inputFn) {
+ var fn = this.$filter(this.consume().text);
+ var argsFn;
+ var args;
+
+ if (this.peek(':')) {
+ argsFn = [];
+ args = []; // we can safely reuse the array
+ while (this.expect(':')) {
+ argsFn.push(this.expression());
+ }
+ }
+
+ var inputs = [inputFn].concat(argsFn || []);
+
+ return extend(function $parseFilter(self, locals) {
+ var input = inputFn(self, locals);
+ if (args) {
+ args[0] = input;
+
+ var i = argsFn.length;
+ while (i--) {
+ args[i + 1] = argsFn[i](self, locals);
+ }
+
+ return fn.apply(undefined, args);
+ }
+
+ return fn(input);
+ }, {
+ constant: !fn.$stateful && inputs.every(isConstant),
+ inputs: !fn.$stateful && inputs
+ });
+ },
+
+ expression: function() {
+ return this.assignment();
+ },
+
+ assignment: function() {
+ var left = this.ternary();
+ var right;
+ var token;
+ if ((token = this.expect('='))) {
+ if (!left.assign) {
+ this.throwError('implies assignment but [' +
+ this.text.substring(0, token.index) + '] can not be assigned to', token);
+ }
+ right = this.ternary();
+ return extend(function $parseAssignment(scope, locals) {
+ return left.assign(scope, right(scope, locals), locals);
+ }, {
+ inputs: [left, right]
+ });
+ }
+ return left;
+ },
+
+ ternary: function() {
+ var left = this.logicalOR();
+ var middle;
+ var token;
+ if ((token = this.expect('?'))) {
+ middle = this.assignment();
+ if (this.consume(':')) {
+ var right = this.assignment();
+
+ return extend(function $parseTernary(self, locals) {
+ return left(self, locals) ? middle(self, locals) : right(self, locals);
+ }, {
+ constant: left.constant && middle.constant && right.constant
+ });
+ }
+ }
+
+ return left;
+ },
+
+ logicalOR: function() {
+ var left = this.logicalAND();
+ var token;
+ while ((token = this.expect('||'))) {
+ left = this.binaryFn(left, token.text, this.logicalAND(), true);
+ }
+ return left;
+ },
+
+ logicalAND: function() {
+ var left = this.equality();
+ var token;
+ while ((token = this.expect('&&'))) {
+ left = this.binaryFn(left, token.text, this.equality(), true);
+ }
+ return left;
+ },
+
+ equality: function() {
+ var left = this.relational();
+ var token;
+ while ((token = this.expect('==','!=','===','!=='))) {
+ left = this.binaryFn(left, token.text, this.relational());
+ }
+ return left;
+ },
+
+ relational: function() {
+ var left = this.additive();
+ var token;
+ while ((token = this.expect('<', '>', '<=', '>='))) {
+ left = this.binaryFn(left, token.text, this.additive());
+ }
+ return left;
+ },
+
+ additive: function() {
+ var left = this.multiplicative();
+ var token;
+ while ((token = this.expect('+','-'))) {
+ left = this.binaryFn(left, token.text, this.multiplicative());
+ }
+ return left;
+ },
+
+ multiplicative: function() {
+ var left = this.unary();
+ var token;
+ while ((token = this.expect('*','/','%'))) {
+ left = this.binaryFn(left, token.text, this.unary());
+ }
+ return left;
+ },
+
+ unary: function() {
+ var token;
+ if (this.expect('+')) {
+ return this.primary();
+ } else if ((token = this.expect('-'))) {
+ return this.binaryFn(Parser.ZERO, token.text, this.unary());
+ } else if ((token = this.expect('!'))) {
+ return this.unaryFn(token.text, this.unary());
+ } else {
+ return this.primary();
+ }
+ },
+
+ fieldAccess: function(object) {
+ var getter = this.identifier();
+
+ return extend(function $parseFieldAccess(scope, locals, self) {
+ var o = self || object(scope, locals);
+ return (o == null) ? undefined : getter(o);
+ }, {
+ assign: function(scope, value, locals) {
+ var o = object(scope, locals);
+ if (!o) object.assign(scope, o = {}, locals);
+ return getter.assign(o, value);
+ }
+ });
+ },
+
+ objectIndex: function(obj) {
+ var expression = this.text;
+
+ var indexFn = this.expression();
+ this.consume(']');
+
+ return extend(function $parseObjectIndex(self, locals) {
+ var o = obj(self, locals),
+ i = getStringValue(indexFn(self, locals), expression),
+ v;
+
+ ensureSafeMemberName(i, expression);
+ if (!o) return undefined;
+ v = ensureSafeObject(o[i], expression);
+ return v;
+ }, {
+ assign: function(self, value, locals) {
+ var key = ensureSafeMemberName(getStringValue(indexFn(self, locals), expression), expression);
+ // prevent overwriting of Function.constructor which would break ensureSafeObject check
+ var o = ensureSafeObject(obj(self, locals), expression);
+ if (!o) obj.assign(self, o = {}, locals);
+ return o[key] = value;
+ }
+ });
+ },
+
+ functionCall: function(fnGetter, contextGetter) {
+ var argsFn = [];
+ if (this.peekToken().text !== ')') {
+ do {
+ argsFn.push(this.expression());
+ } while (this.expect(','));
+ }
+ this.consume(')');
+
+ var expressionText = this.text;
+ // we can safely reuse the array across invocations
+ var args = argsFn.length ? [] : null;
+
+ return function $parseFunctionCall(scope, locals) {
+ var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;
+ var fn = fnGetter(scope, locals, context) || noop;
+
+ if (args) {
+ var i = argsFn.length;
+ while (i--) {
+ args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);
+ }
+ }
+
+ ensureSafeObject(context, expressionText);
+ ensureSafeFunction(fn, expressionText);
+
+ // IE doesn't have apply for some native functions
+ var v = fn.apply
+ ? fn.apply(context, args)
+ : fn(args[0], args[1], args[2], args[3], args[4]);
+
+ if (args) {
+ // Free-up the memory (arguments of the last function call).
+ args.length = 0;
+ }
+
+ return ensureSafeObject(v, expressionText);
+ };
+ },
+
+ // This is used with json array declaration
+ arrayDeclaration: function() {
+ var elementFns = [];
+ if (this.peekToken().text !== ']') {
+ do {
+ if (this.peek(']')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
+ elementFns.push(this.expression());
+ } while (this.expect(','));
+ }
+ this.consume(']');
+
+ return extend(function $parseArrayLiteral(self, locals) {
+ var array = [];
+ for (var i = 0, ii = elementFns.length; i < ii; i++) {
+ array.push(elementFns[i](self, locals));
+ }
+ return array;
+ }, {
+ literal: true,
+ constant: elementFns.every(isConstant),
+ inputs: elementFns
+ });
+ },
+
+ object: function() {
+ var keys = [], valueFns = [];
+ if (this.peekToken().text !== '}') {
+ do {
+ if (this.peek('}')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
+ var token = this.consume();
+ if (token.constant) {
+ keys.push(token.value);
+ } else if (token.identifier) {
+ keys.push(token.text);
+ } else {
+ this.throwError("invalid key", token);
+ }
+ this.consume(':');
+ valueFns.push(this.expression());
+ } while (this.expect(','));
+ }
+ this.consume('}');
+
+ return extend(function $parseObjectLiteral(self, locals) {
+ var object = {};
+ for (var i = 0, ii = valueFns.length; i < ii; i++) {
+ object[keys[i]] = valueFns[i](self, locals);
+ }
+ return object;
+ }, {
+ literal: true,
+ constant: valueFns.every(isConstant),
+ inputs: valueFns
+ });
+ }
+};
+
+
+//////////////////////////////////////////////////
+// Parser helper functions
+//////////////////////////////////////////////////
+
+function setter(obj, locals, path, setValue, fullExp) {
+ ensureSafeObject(obj, fullExp);
+ ensureSafeObject(locals, fullExp);
+
+ var element = path.split('.'), key;
+ for (var i = 0; element.length > 1; i++) {
+ key = ensureSafeMemberName(element.shift(), fullExp);
+ var propertyObj = (i === 0 && locals && locals[key]) || obj[key];
+ if (!propertyObj) {
+ propertyObj = {};
+ obj[key] = propertyObj;
+ }
+ obj = ensureSafeObject(propertyObj, fullExp);
+ }
+ key = ensureSafeMemberName(element.shift(), fullExp);
+ ensureSafeObject(obj[key], fullExp);
+ obj[key] = setValue;
+ return setValue;
+}
+
+var getterFnCacheDefault = createMap();
+var getterFnCacheExpensive = createMap();
+
+function isPossiblyDangerousMemberName(name) {
+ return name == 'constructor';
+}
+
+/**
+ * Implementation of the "Black Hole" variant from:
+ * - http://jsperf.com/angularjs-parse-getter/4
+ * - http://jsperf.com/path-evaluation-simplified/7
+ */
+function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {
+ ensureSafeMemberName(key0, fullExp);
+ ensureSafeMemberName(key1, fullExp);
+ ensureSafeMemberName(key2, fullExp);
+ ensureSafeMemberName(key3, fullExp);
+ ensureSafeMemberName(key4, fullExp);
+ var eso = function(o) {
+ return ensureSafeObject(o, fullExp);
+ };
+ var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;
+ var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;
+ var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;
+ var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;
+ var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;
+
+ return function cspSafeGetter(scope, locals) {
+ var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
+
+ if (pathVal == null) return pathVal;
+ pathVal = eso0(pathVal[key0]);
+
+ if (!key1) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso1(pathVal[key1]);
+
+ if (!key2) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso2(pathVal[key2]);
+
+ if (!key3) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso3(pathVal[key3]);
+
+ if (!key4) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = eso4(pathVal[key4]);
+
+ return pathVal;
+ };
+}
+
+function getterFnWithEnsureSafeObject(fn, fullExpression) {
+ return function(s, l) {
+ return fn(s, l, ensureSafeObject, fullExpression);
+ };
+}
+
+function getterFn(path, options, fullExp) {
+ var expensiveChecks = options.expensiveChecks;
+ var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);
+ var fn = getterFnCache[path];
+ if (fn) return fn;
+
+
+ var pathKeys = path.split('.'),
+ pathKeysLength = pathKeys.length;
+
+ // http://jsperf.com/angularjs-parse-getter/6
+ if (options.csp) {
+ if (pathKeysLength < 6) {
+ fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);
+ } else {
+ fn = function cspSafeGetter(scope, locals) {
+ var i = 0, val;
+ do {
+ val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
+ pathKeys[i++], fullExp, expensiveChecks)(scope, locals);
+
+ locals = undefined; // clear after first iteration
+ scope = val;
+ } while (i < pathKeysLength);
+ return val;
+ };
+ }
+ } else {
+ var code = '';
+ if (expensiveChecks) {
+ code += 's = eso(s, fe);\nl = eso(l, fe);\n';
+ }
+ var needsEnsureSafeObject = expensiveChecks;
+ forEach(pathKeys, function(key, index) {
+ ensureSafeMemberName(key, fullExp);
+ var lookupJs = (index
+ // we simply dereference 's' on any .dot notation
+ ? 's'
+ // but if we are first then we check locals first, and if so read it first
+ : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '.' + key;
+ if (expensiveChecks || isPossiblyDangerousMemberName(key)) {
+ lookupJs = 'eso(' + lookupJs + ', fe)';
+ needsEnsureSafeObject = true;
+ }
+ code += 'if(s == null) return undefined;\n' +
+ 's=' + lookupJs + ';\n';
+ });
+ code += 'return s;';
+
+ /* jshint -W054 */
+ var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject
+ /* jshint +W054 */
+ evaledFnGetter.toString = valueFn(code);
+ if (needsEnsureSafeObject) {
+ evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);
+ }
+ fn = evaledFnGetter;
+ }
+
+ fn.sharedGetter = true;
+ fn.assign = function(self, value, locals) {
+ return setter(self, locals, path, value, path);
+ };
+ getterFnCache[path] = fn;
+ return fn;
+}
+
+var objectValueOf = Object.prototype.valueOf;
+
+function getValueOf(value) {
+ return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
+}
+
+///////////////////////////////////
+
+/**
+ * @ngdoc service
+ * @name $parse
+ * @kind function
+ *
+ * @description
+ *
+ * Converts Angular {@link guide/expression expression} into a function.
+ *
+ * ```js
+ * var getter = $parse('user.name');
+ * var setter = getter.assign;
+ * var context = {user:{name:'angular'}};
+ * var locals = {user:{name:'local'}};
+ *
+ * expect(getter(context)).toEqual('angular');
+ * setter(context, 'newValue');
+ * expect(context.user.name).toEqual('newValue');
+ * expect(getter(context, locals)).toEqual('local');
+ * ```
+ *
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ *
+ * The returned function also has the following properties:
+ * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
+ * literal.
+ * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
+ * constant literals.
+ * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
+ * set to a function to change its value on the given context.
+ *
+ */
+
+
+/**
+ * @ngdoc provider
+ * @name $parseProvider
+ *
+ * @description
+ * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
+ * service.
+ */
+function $ParseProvider() {
+ var cacheDefault = createMap();
+ var cacheExpensive = createMap();
+
+
+
+ this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
+ var $parseOptions = {
+ csp: $sniffer.csp,
+ expensiveChecks: false
+ },
+ $parseOptionsExpensive = {
+ csp: $sniffer.csp,
+ expensiveChecks: true
+ };
+
+ function wrapSharedExpression(exp) {
+ var wrapped = exp;
+
+ if (exp.sharedGetter) {
+ wrapped = function $parseWrapper(self, locals) {
+ return exp(self, locals);
+ };
+ wrapped.literal = exp.literal;
+ wrapped.constant = exp.constant;
+ wrapped.assign = exp.assign;
+ }
+
+ return wrapped;
+ }
+
+ return function $parse(exp, interceptorFn, expensiveChecks) {
+ var parsedExpression, oneTime, cacheKey;
+
+ switch (typeof exp) {
+ case 'string':
+ cacheKey = exp = exp.trim();
+
+ var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
+ parsedExpression = cache[cacheKey];
+
+ if (!parsedExpression) {
+ if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
+ oneTime = true;
+ exp = exp.substring(2);
+ }
+
+ var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
+ var lexer = new Lexer(parseOptions);
+ var parser = new Parser(lexer, $filter, parseOptions);
+ parsedExpression = parser.parse(exp);
+
+ if (parsedExpression.constant) {
+ parsedExpression.$$watchDelegate = constantWatchDelegate;
+ } else if (oneTime) {
+ //oneTime is not part of the exp passed to the Parser so we may have to
+ //wrap the parsedExpression before adding a $$watchDelegate
+ parsedExpression = wrapSharedExpression(parsedExpression);
+ parsedExpression.$$watchDelegate = parsedExpression.literal ?
+ oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
+ } else if (parsedExpression.inputs) {
+ parsedExpression.$$watchDelegate = inputsWatchDelegate;
+ }
+
+ cache[cacheKey] = parsedExpression;
+ }
+ return addInterceptor(parsedExpression, interceptorFn);
+
+ case 'function':
+ return addInterceptor(exp, interceptorFn);
+
+ default:
+ return addInterceptor(noop, interceptorFn);
+ }
+ };
+
+ function collectExpressionInputs(inputs, list) {
+ for (var i = 0, ii = inputs.length; i < ii; i++) {
+ var input = inputs[i];
+ if (!input.constant) {
+ if (input.inputs) {
+ collectExpressionInputs(input.inputs, list);
+ } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better?
+ list.push(input);
+ }
+ }
+ }
+
+ return list;
+ }
+
+ function expressionInputDirtyCheck(newValue, oldValueOfValue) {
+
+ if (newValue == null || oldValueOfValue == null) { // null/undefined
+ return newValue === oldValueOfValue;
+ }
+
+ if (typeof newValue === 'object') {
+
+ // attempt to convert the value to a primitive type
+ // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
+ // be cheaply dirty-checked
+ newValue = getValueOf(newValue);
+
+ if (typeof newValue === 'object') {
+ // objects/arrays are not supported - deep-watching them would be too expensive
+ return false;
+ }
+
+ // fall-through to the primitive equality check
+ }
+
+ //Primitive or NaN
+ return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
+ }
+
+ function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var inputExpressions = parsedExpression.$$inputs ||
+ (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, []));
+
+ var lastResult;
+
+ if (inputExpressions.length === 1) {
+ var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails
+ inputExpressions = inputExpressions[0];
+ return scope.$watch(function expressionInputWatch(scope) {
+ var newInputValue = inputExpressions(scope);
+ if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {
+ lastResult = parsedExpression(scope);
+ oldInputValue = newInputValue && getValueOf(newInputValue);
+ }
+ return lastResult;
+ }, listener, objectEquality);
+ }
+
+ var oldInputValueOfValues = [];
+ for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
+ oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
+ }
+
+ return scope.$watch(function expressionInputsWatch(scope) {
+ var changed = false;
+
+ for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
+ var newInputValue = inputExpressions[i](scope);
+ if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
+ oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
+ }
+ }
+
+ if (changed) {
+ lastResult = parsedExpression(scope);
+ }
+
+ return lastResult;
+ }, listener, objectEquality);
+ }
+
+ function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch, lastValue;
+ return unwatch = scope.$watch(function oneTimeWatch(scope) {
+ return parsedExpression(scope);
+ }, function oneTimeListener(value, old, scope) {
+ lastValue = value;
+ if (isFunction(listener)) {
+ listener.apply(this, arguments);
+ }
+ if (isDefined(value)) {
+ scope.$$postDigest(function() {
+ if (isDefined(lastValue)) {
+ unwatch();
+ }
+ });
+ }
+ }, objectEquality);
+ }
+
+ function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch, lastValue;
+ return unwatch = scope.$watch(function oneTimeWatch(scope) {
+ return parsedExpression(scope);
+ }, function oneTimeListener(value, old, scope) {
+ lastValue = value;
+ if (isFunction(listener)) {
+ listener.call(this, value, old, scope);
+ }
+ if (isAllDefined(value)) {
+ scope.$$postDigest(function() {
+ if (isAllDefined(lastValue)) unwatch();
+ });
+ }
+ }, objectEquality);
+
+ function isAllDefined(value) {
+ var allDefined = true;
+ forEach(value, function(val) {
+ if (!isDefined(val)) allDefined = false;
+ });
+ return allDefined;
+ }
+ }
+
+ function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch;
+ return unwatch = scope.$watch(function constantWatch(scope) {
+ return parsedExpression(scope);
+ }, function constantListener(value, old, scope) {
+ if (isFunction(listener)) {
+ listener.apply(this, arguments);
+ }
+ unwatch();
+ }, objectEquality);
+ }
+
+ function addInterceptor(parsedExpression, interceptorFn) {
+ if (!interceptorFn) return parsedExpression;
+ var watchDelegate = parsedExpression.$$watchDelegate;
+
+ var regularWatch =
+ watchDelegate !== oneTimeLiteralWatchDelegate &&
+ watchDelegate !== oneTimeWatchDelegate;
+
+ var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {
+ var value = parsedExpression(scope, locals);
+ return interceptorFn(value, scope, locals);
+ } : function oneTimeInterceptedExpression(scope, locals) {
+ var value = parsedExpression(scope, locals);
+ var result = interceptorFn(value, scope, locals);
+ // we only return the interceptor's result if the
+ // initial value is defined (for bind-once)
+ return isDefined(value) ? result : value;
+ };
+
+ // Propagate $$watchDelegates other then inputsWatchDelegate
+ if (parsedExpression.$$watchDelegate &&
+ parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
+ fn.$$watchDelegate = parsedExpression.$$watchDelegate;
+ } else if (!interceptorFn.$stateful) {
+ // If there is an interceptor, but no watchDelegate then treat the interceptor like
+ // we treat filters - it is assumed to be a pure function unless flagged with $stateful
+ fn.$$watchDelegate = inputsWatchDelegate;
+ fn.inputs = [parsedExpression];
+ }
+
+ return fn;
+ }
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $q
+ * @requires $rootScope
+ *
+ * @description
+ * A service that helps you run functions asynchronously, and use their return values (or exceptions)
+ * when they are done processing.
+ *
+ * This is an implementation of promises/deferred objects inspired by
+ * [Kris Kowal's Q](https://github.com/kriskowal/q).
+ *
+ * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
+ * implementations, and the other which resembles ES6 promises to some degree.
+ *
+ * # $q constructor
+ *
+ * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`
+ * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,
+ * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
+ *
+ * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are
+ * available yet.
+ *
+ * It can be used like so:
+ *
+ * ```js
+ * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
+ * // are available in the current lexical scope (they could have been injected or passed in).
+ *
+ * function asyncGreet(name) {
+ * // perform some asynchronous operation, resolve or reject the promise when appropriate.
+ * return $q(function(resolve, reject) {
+ * setTimeout(function() {
+ * if (okToGreet(name)) {
+ * resolve('Hello, ' + name + '!');
+ * } else {
+ * reject('Greeting ' + name + ' is not allowed.');
+ * }
+ * }, 1000);
+ * });
+ * }
+ *
+ * var promise = asyncGreet('Robin Hood');
+ * promise.then(function(greeting) {
+ * alert('Success: ' + greeting);
+ * }, function(reason) {
+ * alert('Failed: ' + reason);
+ * });
+ * ```
+ *
+ * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
+ *
+ * However, the more traditional CommonJS-style usage is still available, and documented below.
+ *
+ * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
+ * interface for interacting with an object that represents the result of an action that is
+ * performed asynchronously, and may or may not be finished at any given point in time.
+ *
+ * From the perspective of dealing with error handling, deferred and promise APIs are to
+ * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
+ *
+ * ```js
+ * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
+ * // are available in the current lexical scope (they could have been injected or passed in).
+ *
+ * function asyncGreet(name) {
+ * var deferred = $q.defer();
+ *
+ * setTimeout(function() {
+ * deferred.notify('About to greet ' + name + '.');
+ *
+ * if (okToGreet(name)) {
+ * deferred.resolve('Hello, ' + name + '!');
+ * } else {
+ * deferred.reject('Greeting ' + name + ' is not allowed.');
+ * }
+ * }, 1000);
+ *
+ * return deferred.promise;
+ * }
+ *
+ * var promise = asyncGreet('Robin Hood');
+ * promise.then(function(greeting) {
+ * alert('Success: ' + greeting);
+ * }, function(reason) {
+ * alert('Failed: ' + reason);
+ * }, function(update) {
+ * alert('Got notification: ' + update);
+ * });
+ * ```
+ *
+ * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
+ * comes in the way of guarantees that promise and deferred APIs make, see
+ * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
+ *
+ * Additionally the promise api allows for composition that is very hard to do with the
+ * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
+ * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
+ * section on serial or parallel joining of promises.
+ *
+ * # The Deferred API
+ *
+ * A new instance of deferred is constructed by calling `$q.defer()`.
+ *
+ * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
+ * that can be used for signaling the successful or unsuccessful completion, as well as the status
+ * of the task.
+ *
+ * **Methods**
+ *
+ * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
+ * constructed via `$q.reject`, the promise will be rejected instead.
+ * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
+ * resolving it with a rejection constructed via `$q.reject`.
+ * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
+ * multiple times before the promise is either resolved or rejected.
+ *
+ * **Properties**
+ *
+ * - promise – `{Promise}` – promise object associated with this deferred.
+ *
+ *
+ * # The Promise API
+ *
+ * A new promise instance is created when a deferred instance is created and can be retrieved by
+ * calling `deferred.promise`.
+ *
+ * The purpose of the promise object is to allow for interested parties to get access to the result
+ * of the deferred task when it completes.
+ *
+ * **Methods**
+ *
+ * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
+ * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
+ * as soon as the result is available. The callbacks are called with a single argument: the result
+ * or rejection reason. Additionally, the notify callback may be called zero or more times to
+ * provide a progress indication, before the promise is resolved or rejected.
+ *
+ * This method *returns a new promise* which is resolved or rejected via the return value of the
+ * `successCallback`, `errorCallback`. It also notifies via the return value of the
+ * `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback
+ * method.
+ *
+ * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
+ *
+ * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
+ * but to do so without modifying the final value. This is useful to release resources or do some
+ * clean-up that needs to be done whether the promise was rejected or resolved. See the [full
+ * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
+ * more information.
+ *
+ * # Chaining promises
+ *
+ * Because calling the `then` method of a promise returns a new derived promise, it is easily
+ * possible to create a chain of promises:
+ *
+ * ```js
+ * promiseB = promiseA.then(function(result) {
+ * return result + 1;
+ * });
+ *
+ * // promiseB will be resolved immediately after promiseA is resolved and its value
+ * // will be the result of promiseA incremented by 1
+ * ```
+ *
+ * It is possible to create chains of any length and since a promise can be resolved with another
+ * promise (which will defer its resolution further), it is possible to pause/defer resolution of
+ * the promises at any point in the chain. This makes it possible to implement powerful APIs like
+ * $http's response interceptors.
+ *
+ *
+ * # Differences between Kris Kowal's Q and $q
+ *
+ * There are two main differences:
+ *
+ * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
+ * mechanism in angular, which means faster propagation of resolution or rejection into your
+ * models and avoiding unnecessary browser repaints, which would result in flickering UI.
+ * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
+ * all the important functionality needed for common async tasks.
+ *
+ * # Testing
+ *
+ * ```js
+ * it('should simulate promise', inject(function($q, $rootScope) {
+ * var deferred = $q.defer();
+ * var promise = deferred.promise;
+ * var resolvedValue;
+ *
+ * promise.then(function(value) { resolvedValue = value; });
+ * expect(resolvedValue).toBeUndefined();
+ *
+ * // Simulate resolving of promise
+ * deferred.resolve(123);
+ * // Note that the 'then' function does not get called synchronously.
+ * // This is because we want the promise API to always be async, whether or not
+ * // it got called synchronously or asynchronously.
+ * expect(resolvedValue).toBeUndefined();
+ *
+ * // Propagate promise resolution to 'then' functions using $apply().
+ * $rootScope.$apply();
+ * expect(resolvedValue).toEqual(123);
+ * }));
+ * ```
+ *
+ * @param {function(function, function)} resolver Function which is responsible for resolving or
+ * rejecting the newly created promise. The first parameter is a function which resolves the
+ * promise, the second parameter is a function which rejects the promise.
+ *
+ * @returns {Promise} The newly created promise.
+ */
+function $QProvider() {
+
+ this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
+ return qFactory(function(callback) {
+ $rootScope.$evalAsync(callback);
+ }, $exceptionHandler);
+ }];
+}
+
+function $$QProvider() {
+ this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
+ return qFactory(function(callback) {
+ $browser.defer(callback);
+ }, $exceptionHandler);
+ }];
+}
+
+/**
+ * Constructs a promise manager.
+ *
+ * @param {function(function)} nextTick Function for executing functions in the next turn.
+ * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
+ * debugging purposes.
+ * @returns {object} Promise manager.
+ */
+function qFactory(nextTick, exceptionHandler) {
+ var $qMinErr = minErr('$q', TypeError);
+ function callOnce(self, resolveFn, rejectFn) {
+ var called = false;
+ function wrap(fn) {
+ return function(value) {
+ if (called) return;
+ called = true;
+ fn.call(self, value);
+ };
+ }
+
+ return [wrap(resolveFn), wrap(rejectFn)];
+ }
+
+ /**
+ * @ngdoc method
+ * @name ng.$q#defer
+ * @kind function
+ *
+ * @description
+ * Creates a `Deferred` object which represents a task which will finish in the future.
+ *
+ * @returns {Deferred} Returns a new instance of deferred.
+ */
+ var defer = function() {
+ return new Deferred();
+ };
+
+ function Promise() {
+ this.$$state = { status: 0 };
+ }
+
+ Promise.prototype = {
+ then: function(onFulfilled, onRejected, progressBack) {
+ var result = new Deferred();
+
+ this.$$state.pending = this.$$state.pending || [];
+ this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
+ if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
+
+ return result.promise;
+ },
+
+ "catch": function(callback) {
+ return this.then(null, callback);
+ },
+
+ "finally": function(callback, progressBack) {
+ return this.then(function(value) {
+ return handleCallback(value, true, callback);
+ }, function(error) {
+ return handleCallback(error, false, callback);
+ }, progressBack);
+ }
+ };
+
+ //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
+ function simpleBind(context, fn) {
+ return function(value) {
+ fn.call(context, value);
+ };
+ }
+
+ function processQueue(state) {
+ var fn, promise, pending;
+
+ pending = state.pending;
+ state.processScheduled = false;
+ state.pending = undefined;
+ for (var i = 0, ii = pending.length; i < ii; ++i) {
+ promise = pending[i][0];
+ fn = pending[i][state.status];
+ try {
+ if (isFunction(fn)) {
+ promise.resolve(fn(state.value));
+ } else if (state.status === 1) {
+ promise.resolve(state.value);
+ } else {
+ promise.reject(state.value);
+ }
+ } catch (e) {
+ promise.reject(e);
+ exceptionHandler(e);
+ }
+ }
+ }
+
+ function scheduleProcessQueue(state) {
+ if (state.processScheduled || !state.pending) return;
+ state.processScheduled = true;
+ nextTick(function() { processQueue(state); });
+ }
+
+ function Deferred() {
+ this.promise = new Promise();
+ //Necessary to support unbound execution :/
+ this.resolve = simpleBind(this, this.resolve);
+ this.reject = simpleBind(this, this.reject);
+ this.notify = simpleBind(this, this.notify);
+ }
+
+ Deferred.prototype = {
+ resolve: function(val) {
+ if (this.promise.$$state.status) return;
+ if (val === this.promise) {
+ this.$$reject($qMinErr(
+ 'qcycle',
+ "Expected promise to be resolved with value other than itself '{0}'",
+ val));
+ } else {
+ this.$$resolve(val);
+ }
+
+ },
+
+ $$resolve: function(val) {
+ var then, fns;
+
+ fns = callOnce(this, this.$$resolve, this.$$reject);
+ try {
+ if ((isObject(val) || isFunction(val))) then = val && val.then;
+ if (isFunction(then)) {
+ this.promise.$$state.status = -1;
+ then.call(val, fns[0], fns[1], this.notify);
+ } else {
+ this.promise.$$state.value = val;
+ this.promise.$$state.status = 1;
+ scheduleProcessQueue(this.promise.$$state);
+ }
+ } catch (e) {
+ fns[1](e);
+ exceptionHandler(e);
+ }
+ },
+
+ reject: function(reason) {
+ if (this.promise.$$state.status) return;
+ this.$$reject(reason);
+ },
+
+ $$reject: function(reason) {
+ this.promise.$$state.value = reason;
+ this.promise.$$state.status = 2;
+ scheduleProcessQueue(this.promise.$$state);
+ },
+
+ notify: function(progress) {
+ var callbacks = this.promise.$$state.pending;
+
+ if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {
+ nextTick(function() {
+ var callback, result;
+ for (var i = 0, ii = callbacks.length; i < ii; i++) {
+ result = callbacks[i][0];
+ callback = callbacks[i][3];
+ try {
+ result.notify(isFunction(callback) ? callback(progress) : progress);
+ } catch (e) {
+ exceptionHandler(e);
+ }
+ }
+ });
+ }
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#reject
+ * @kind function
+ *
+ * @description
+ * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
+ * used to forward rejection in a chain of promises. If you are dealing with the last promise in
+ * a promise chain, you don't need to worry about it.
+ *
+ * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
+ * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
+ * a promise error callback and you want to forward the error to the promise derived from the
+ * current promise, you have to "rethrow" the error by returning a rejection constructed via
+ * `reject`.
+ *
+ * ```js
+ * promiseB = promiseA.then(function(result) {
+ * // success: do something and resolve promiseB
+ * // with the old or a new result
+ * return result;
+ * }, function(reason) {
+ * // error: handle the error if possible and
+ * // resolve promiseB with newPromiseOrValue,
+ * // otherwise forward the rejection to promiseB
+ * if (canHandle(reason)) {
+ * // handle the error and recover
+ * return newPromiseOrValue;
+ * }
+ * return $q.reject(reason);
+ * });
+ * ```
+ *
+ * @param {*} reason Constant, message, exception or an object representing the rejection reason.
+ * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
+ */
+ var reject = function(reason) {
+ var result = new Deferred();
+ result.reject(reason);
+ return result.promise;
+ };
+
+ var makePromise = function makePromise(value, resolved) {
+ var result = new Deferred();
+ if (resolved) {
+ result.resolve(value);
+ } else {
+ result.reject(value);
+ }
+ return result.promise;
+ };
+
+ var handleCallback = function handleCallback(value, isResolved, callback) {
+ var callbackOutput = null;
+ try {
+ if (isFunction(callback)) callbackOutput = callback();
+ } catch (e) {
+ return makePromise(e, false);
+ }
+ if (isPromiseLike(callbackOutput)) {
+ return callbackOutput.then(function() {
+ return makePromise(value, isResolved);
+ }, function(error) {
+ return makePromise(error, false);
+ });
+ } else {
+ return makePromise(value, isResolved);
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#when
+ * @kind function
+ *
+ * @description
+ * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
+ * This is useful when you are dealing with an object that might or might not be a promise, or if
+ * the promise comes from a source that can't be trusted.
+ *
+ * @param {*} value Value or a promise
+ * @returns {Promise} Returns a promise of the passed value or promise
+ */
+
+
+ var when = function(value, callback, errback, progressBack) {
+ var result = new Deferred();
+ result.resolve(value);
+ return result.promise.then(callback, errback, progressBack);
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#all
+ * @kind function
+ *
+ * @description
+ * Combines multiple promises into a single promise that is resolved when all of the input
+ * promises are resolved.
+ *
+ * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
+ * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
+ * each value corresponding to the promise at the same index/key in the `promises` array/hash.
+ * If any of the promises is resolved with a rejection, this resulting promise will be rejected
+ * with the same rejection value.
+ */
+
+ function all(promises) {
+ var deferred = new Deferred(),
+ counter = 0,
+ results = isArray(promises) ? [] : {};
+
+ forEach(promises, function(promise, key) {
+ counter++;
+ when(promise).then(function(value) {
+ if (results.hasOwnProperty(key)) return;
+ results[key] = value;
+ if (!(--counter)) deferred.resolve(results);
+ }, function(reason) {
+ if (results.hasOwnProperty(key)) return;
+ deferred.reject(reason);
+ });
+ });
+
+ if (counter === 0) {
+ deferred.resolve(results);
+ }
+
+ return deferred.promise;
+ }
+
+ var $Q = function Q(resolver) {
+ if (!isFunction(resolver)) {
+ throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
+ }
+
+ if (!(this instanceof Q)) {
+ // More useful when $Q is the Promise itself.
+ return new Q(resolver);
+ }
+
+ var deferred = new Deferred();
+
+ function resolveFn(value) {
+ deferred.resolve(value);
+ }
+
+ function rejectFn(reason) {
+ deferred.reject(reason);
+ }
+
+ resolver(resolveFn, rejectFn);
+
+ return deferred.promise;
+ };
+
+ $Q.defer = defer;
+ $Q.reject = reject;
+ $Q.when = when;
+ $Q.all = all;
+
+ return $Q;
+}
+
+function $$RAFProvider() { //rAF
+ this.$get = ['$window', '$timeout', function($window, $timeout) {
+ var requestAnimationFrame = $window.requestAnimationFrame ||
+ $window.webkitRequestAnimationFrame;
+
+ var cancelAnimationFrame = $window.cancelAnimationFrame ||
+ $window.webkitCancelAnimationFrame ||
+ $window.webkitCancelRequestAnimationFrame;
+
+ var rafSupported = !!requestAnimationFrame;
+ var rafFn = rafSupported
+ ? function(fn) {
+ var id = requestAnimationFrame(fn);
+ return function() {
+ cancelAnimationFrame(id);
+ };
+ }
+ : function(fn) {
+ var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
+ return function() {
+ $timeout.cancel(timer);
+ };
+ };
+
+ queueFn.supported = rafSupported;
+
+ var cancelLastRAF;
+ var taskCount = 0;
+ var taskQueue = [];
+ return queueFn;
+
+ function flush() {
+ for (var i = 0; i < taskQueue.length; i++) {
+ var task = taskQueue[i];
+ if (task) {
+ taskQueue[i] = null;
+ task();
+ }
+ }
+ taskCount = taskQueue.length = 0;
+ }
+
+ function queueFn(asyncFn) {
+ var index = taskQueue.length;
+
+ taskCount++;
+ taskQueue.push(asyncFn);
+
+ if (index === 0) {
+ cancelLastRAF = rafFn(flush);
+ }
+
+ return function cancelQueueFn() {
+ if (index >= 0) {
+ taskQueue[index] = null;
+ index = null;
+
+ if (--taskCount === 0 && cancelLastRAF) {
+ cancelLastRAF();
+ cancelLastRAF = null;
+ taskQueue.length = 0;
+ }
+ }
+ };
+ }
+ }];
+}
+
+/**
+ * DESIGN NOTES
+ *
+ * The design decisions behind the scope are heavily favored for speed and memory consumption.
+ *
+ * The typical use of scope is to watch the expressions, which most of the time return the same
+ * value as last time so we optimize the operation.
+ *
+ * Closures construction is expensive in terms of speed as well as memory:
+ * - No closures, instead use prototypical inheritance for API
+ * - Internal state needs to be stored on scope directly, which means that private state is
+ * exposed as $$____ properties
+ *
+ * Loop operations are optimized by using while(count--) { ... }
+ * - this means that in order to keep the same order of execution as addition we have to add
+ * items to the array at the beginning (unshift) instead of at the end (push)
+ *
+ * Child scopes are created and removed often
+ * - Using an array would be slow since inserts in middle are expensive so we use linked list
+ *
+ * There are few watches then a lot of observers. This is why you don't want the observer to be
+ * implemented in the same way as watch. Watch requires return of initialization function which
+ * are expensive to construct.
+ */
+
+
+/**
+ * @ngdoc provider
+ * @name $rootScopeProvider
+ * @description
+ *
+ * Provider for the $rootScope service.
+ */
+
+/**
+ * @ngdoc method
+ * @name $rootScopeProvider#digestTtl
+ * @description
+ *
+ * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
+ * assuming that the model is unstable.
+ *
+ * The current default is 10 iterations.
+ *
+ * In complex applications it's possible that the dependencies between `$watch`s will result in
+ * several digest iterations. However if an application needs more than the default 10 digest
+ * iterations for its model to stabilize then you should investigate what is causing the model to
+ * continuously change during the digest.
+ *
+ * Increasing the TTL could have performance implications, so you should not change it without
+ * proper justification.
+ *
+ * @param {number} limit The number of digest iterations.
+ */
+
+
+/**
+ * @ngdoc service
+ * @name $rootScope
+ * @description
+ *
+ * Every application has a single root {@link ng.$rootScope.Scope scope}.
+ * All other scopes are descendant scopes of the root scope. Scopes provide separation
+ * between the model and the view, via a mechanism for watching the model for changes.
+ * They also provide an event emission/broadcast and subscription facility. See the
+ * {@link guide/scope developer guide on scopes}.
+ */
+function $RootScopeProvider() {
+ var TTL = 10;
+ var $rootScopeMinErr = minErr('$rootScope');
+ var lastDirtyWatch = null;
+ var applyAsyncId = null;
+
+ this.digestTtl = function(value) {
+ if (arguments.length) {
+ TTL = value;
+ }
+ return TTL;
+ };
+
+ function createChildScopeClass(parent) {
+ function ChildScope() {
+ this.$$watchers = this.$$nextSibling =
+ this.$$childHead = this.$$childTail = null;
+ this.$$listeners = {};
+ this.$$listenerCount = {};
+ this.$id = nextUid();
+ this.$$ChildScope = null;
+ }
+ ChildScope.prototype = parent;
+ return ChildScope;
+ }
+
+ this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
+ function($injector, $exceptionHandler, $parse, $browser) {
+
+ function destroyChildScope($event) {
+ $event.currentScope.$$destroyed = true;
+ }
+
+ /**
+ * @ngdoc type
+ * @name $rootScope.Scope
+ *
+ * @description
+ * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
+ * {@link auto.$injector $injector}. Child scopes are created using the
+ * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
+ * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for
+ * an in-depth introduction and usage examples.
+ *
+ *
+ * # Inheritance
+ * A scope can inherit from a parent scope, as in this example:
+ * ```js
+ var parent = $rootScope;
+ var child = parent.$new();
+
+ parent.salutation = "Hello";
+ expect(child.salutation).toEqual('Hello');
+
+ child.salutation = "Welcome";
+ expect(child.salutation).toEqual('Welcome');
+ expect(parent.salutation).toEqual('Hello');
+ * ```
+ *
+ * When interacting with `Scope` in tests, additional helper methods are available on the
+ * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional
+ * details.
+ *
+ *
+ * @param {Object.<string, function()>=} providers Map of service factory which need to be
+ * provided for the current scope. Defaults to {@link ng}.
+ * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
+ * append/override services provided by `providers`. This is handy
+ * when unit-testing and having the need to override a default
+ * service.
+ * @returns {Object} Newly created scope.
+ *
+ */
+ function Scope() {
+ this.$id = nextUid();
+ this.$$phase = this.$parent = this.$$watchers =
+ this.$$nextSibling = this.$$prevSibling =
+ this.$$childHead = this.$$childTail = null;
+ this.$root = this;
+ this.$$destroyed = false;
+ this.$$listeners = {};
+ this.$$listenerCount = {};
+ this.$$isolateBindings = null;
+ }
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$id
+ *
+ * @description
+ * Unique scope ID (monotonically increasing) useful for debugging.
+ */
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$parent
+ *
+ * @description
+ * Reference to the parent scope.
+ */
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$root
+ *
+ * @description
+ * Reference to the root scope.
+ */
+
+ Scope.prototype = {
+ constructor: Scope,
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$new
+ * @kind function
+ *
+ * @description
+ * Creates a new child {@link ng.$rootScope.Scope scope}.
+ *
+ * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
+ * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
+ *
+ * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
+ * desired for the scope and its child scopes to be permanently detached from the parent and
+ * thus stop participating in model change detection and listener notification by invoking.
+ *
+ * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
+ * parent scope. The scope is isolated, as it can not see parent scope properties.
+ * When creating widgets, it is useful for the widget to not accidentally read parent
+ * state.
+ *
+ * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`
+ * of the newly created scope. Defaults to `this` scope if not provided.
+ * This is used when creating a transclude scope to correctly place it
+ * in the scope hierarchy while maintaining the correct prototypical
+ * inheritance.
+ *
+ * @returns {Object} The newly created child scope.
+ *
+ */
+ $new: function(isolate, parent) {
+ var child;
+
+ parent = parent || this;
+
+ if (isolate) {
+ child = new Scope();
+ child.$root = this.$root;
+ } else {
+ // Only create a child scope class if somebody asks for one,
+ // but cache it to allow the VM to optimize lookups.
+ if (!this.$$ChildScope) {
+ this.$$ChildScope = createChildScopeClass(this);
+ }
+ child = new this.$$ChildScope();
+ }
+ child.$parent = parent;
+ child.$$prevSibling = parent.$$childTail;
+ if (parent.$$childHead) {
+ parent.$$childTail.$$nextSibling = child;
+ parent.$$childTail = child;
+ } else {
+ parent.$$childHead = parent.$$childTail = child;
+ }
+
+ // When the new scope is not isolated or we inherit from `this`, and
+ // the parent scope is destroyed, the property `$$destroyed` is inherited
+ // prototypically. In all other cases, this property needs to be set
+ // when the parent scope is destroyed.
+ // The listener needs to be added after the parent is set
+ if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
+
+ return child;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watch
+ * @kind function
+ *
+ * @description
+ * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
+ *
+ * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
+ * $digest()} and should return the value that will be watched. (Since
+ * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
+ * `watchExpression` can execute multiple times per
+ * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
+ * - The `listener` is called only when the value from the current `watchExpression` and the
+ * previous call to `watchExpression` are not equal (with the exception of the initial run,
+ * see below). Inequality is determined according to reference inequality,
+ * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
+ * via the `!==` Javascript operator, unless `objectEquality == true`
+ * (see next point)
+ * - When `objectEquality == true`, inequality of the `watchExpression` is determined
+ * according to the {@link angular.equals} function. To save the value of the object for
+ * later comparison, the {@link angular.copy} function is used. This therefore means that
+ * watching complex objects will have adverse memory and performance implications.
+ * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
+ * This is achieved by rerunning the watchers until no changes are detected. The rerun
+ * iteration limit is 10 to prevent an infinite loop deadlock.
+ *
+ *
+ * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
+ * you can register a `watchExpression` function with no `listener`. (Be prepared for
+ * multiple calls to your `watchExpression` because it will execute multiple times in a
+ * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)
+ *
+ * After a watcher is registered with the scope, the `listener` fn is called asynchronously
+ * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
+ * watcher. In rare cases, this is undesirable because the listener is called when the result
+ * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
+ * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
+ * listener was called due to initialization.
+ *
+ *
+ *
+ * # Example
+ * ```js
+ // let's assume that scope was dependency injected as the $rootScope
+ var scope = $rootScope;
+ scope.name = 'misko';
+ scope.counter = 0;
+
+ expect(scope.counter).toEqual(0);
+ scope.$watch('name', function(newValue, oldValue) {
+ scope.counter = scope.counter + 1;
+ });
+ expect(scope.counter).toEqual(0);
+
+ scope.$digest();
+ // the listener is always called during the first $digest loop after it was registered
+ expect(scope.counter).toEqual(1);
+
+ scope.$digest();
+ // but now it will not be called unless the value changes
+ expect(scope.counter).toEqual(1);
+
+ scope.name = 'adam';
+ scope.$digest();
+ expect(scope.counter).toEqual(2);
+
+
+
+ // Using a function as a watchExpression
+ var food;
+ scope.foodCounter = 0;
+ expect(scope.foodCounter).toEqual(0);
+ scope.$watch(
+ // This function returns the value being watched. It is called for each turn of the $digest loop
+ function() { return food; },
+ // This is the change listener, called when the value returned from the above function changes
+ function(newValue, oldValue) {
+ if ( newValue !== oldValue ) {
+ // Only increment the counter if the value changed
+ scope.foodCounter = scope.foodCounter + 1;
+ }
+ }
+ );
+ // No digest has been run so the counter will be zero
+ expect(scope.foodCounter).toEqual(0);
+
+ // Run the digest but since food has not changed count will still be zero
+ scope.$digest();
+ expect(scope.foodCounter).toEqual(0);
+
+ // Update food and run digest. Now the counter will increment
+ food = 'cheeseburger';
+ scope.$digest();
+ expect(scope.foodCounter).toEqual(1);
+
+ * ```
+ *
+ *
+ *
+ * @param {(function()|string)} watchExpression Expression that is evaluated on each
+ * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
+ * a call to the `listener`.
+ *
+ * - `string`: Evaluated as {@link guide/expression expression}
+ * - `function(scope)`: called with current `scope` as a parameter.
+ * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value
+ * of `watchExpression` changes.
+ *
+ * - `newVal` contains the current value of the `watchExpression`
+ * - `oldVal` contains the previous value of the `watchExpression`
+ * - `scope` refers to the current scope
+ * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
+ * comparing for reference equality.
+ * @returns {function()} Returns a deregistration function for this listener.
+ */
+ $watch: function(watchExp, listener, objectEquality) {
+ var get = $parse(watchExp);
+
+ if (get.$$watchDelegate) {
+ return get.$$watchDelegate(this, listener, objectEquality, get);
+ }
+ var scope = this,
+ array = scope.$$watchers,
+ watcher = {
+ fn: listener,
+ last: initWatchVal,
+ get: get,
+ exp: watchExp,
+ eq: !!objectEquality
+ };
+
+ lastDirtyWatch = null;
+
+ if (!isFunction(listener)) {
+ watcher.fn = noop;
+ }
+
+ if (!array) {
+ array = scope.$$watchers = [];
+ }
+ // we use unshift since we use a while loop in $digest for speed.
+ // the while loop reads in reverse order.
+ array.unshift(watcher);
+
+ return function deregisterWatch() {
+ arrayRemove(array, watcher);
+ lastDirtyWatch = null;
+ };
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watchGroup
+ * @kind function
+ *
+ * @description
+ * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
+ * If any one expression in the collection changes the `listener` is executed.
+ *
+ * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
+ * call to $digest() to see if any items changes.
+ * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
+ *
+ * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
+ * watched using {@link ng.$rootScope.Scope#$watch $watch()}
+ *
+ * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
+ * expression in `watchExpressions` changes
+ * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
+ * those of `watchExpression`
+ * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
+ * those of `watchExpression`
+ * The `scope` refers to the current scope.
+ * @returns {function()} Returns a de-registration function for all listeners.
+ */
+ $watchGroup: function(watchExpressions, listener) {
+ var oldValues = new Array(watchExpressions.length);
+ var newValues = new Array(watchExpressions.length);
+ var deregisterFns = [];
+ var self = this;
+ var changeReactionScheduled = false;
+ var firstRun = true;
+
+ if (!watchExpressions.length) {
+ // No expressions means we call the listener ASAP
+ var shouldCall = true;
+ self.$evalAsync(function() {
+ if (shouldCall) listener(newValues, newValues, self);
+ });
+ return function deregisterWatchGroup() {
+ shouldCall = false;
+ };
+ }
+
+ if (watchExpressions.length === 1) {
+ // Special case size of one
+ return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
+ newValues[0] = value;
+ oldValues[0] = oldValue;
+ listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
+ });
+ }
+
+ forEach(watchExpressions, function(expr, i) {
+ var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
+ newValues[i] = value;
+ oldValues[i] = oldValue;
+ if (!changeReactionScheduled) {
+ changeReactionScheduled = true;
+ self.$evalAsync(watchGroupAction);
+ }
+ });
+ deregisterFns.push(unwatchFn);
+ });
+
+ function watchGroupAction() {
+ changeReactionScheduled = false;
+
+ if (firstRun) {
+ firstRun = false;
+ listener(newValues, newValues, self);
+ } else {
+ listener(newValues, oldValues, self);
+ }
+ }
+
+ return function deregisterWatchGroup() {
+ while (deregisterFns.length) {
+ deregisterFns.shift()();
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watchCollection
+ * @kind function
+ *
+ * @description
+ * Shallow watches the properties of an object and fires whenever any of the properties change
+ * (for arrays, this implies watching the array items; for object maps, this implies watching
+ * the properties). If a change is detected, the `listener` callback is fired.
+ *
+ * - The `obj` collection is observed via standard $watch operation and is examined on every
+ * call to $digest() to see if any items have been added, removed, or moved.
+ * - The `listener` is called whenever anything within the `obj` has changed. Examples include
+ * adding, removing, and moving items belonging to an object or array.
+ *
+ *
+ * # Example
+ * ```js
+ $scope.names = ['igor', 'matias', 'misko', 'james'];
+ $scope.dataCount = 4;
+
+ $scope.$watchCollection('names', function(newNames, oldNames) {
+ $scope.dataCount = newNames.length;
+ });
+
+ expect($scope.dataCount).toEqual(4);
+ $scope.$digest();
+
+ //still at 4 ... no changes
+ expect($scope.dataCount).toEqual(4);
+
+ $scope.names.pop();
+ $scope.$digest();
+
+ //now there's been a change
+ expect($scope.dataCount).toEqual(3);
+ * ```
+ *
+ *
+ * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
+ * expression value should evaluate to an object or an array which is observed on each
+ * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
+ * collection will trigger a call to the `listener`.
+ *
+ * @param {function(newCollection, oldCollection, scope)} listener a callback function called
+ * when a change is detected.
+ * - The `newCollection` object is the newly modified data obtained from the `obj` expression
+ * - The `oldCollection` object is a copy of the former collection data.
+ * Due to performance considerations, the`oldCollection` value is computed only if the
+ * `listener` function declares two or more arguments.
+ * - The `scope` argument refers to the current scope.
+ *
+ * @returns {function()} Returns a de-registration function for this listener. When the
+ * de-registration function is executed, the internal watch operation is terminated.
+ */
+ $watchCollection: function(obj, listener) {
+ $watchCollectionInterceptor.$stateful = true;
+
+ var self = this;
+ // the current value, updated on each dirty-check run
+ var newValue;
+ // a shallow copy of the newValue from the last dirty-check run,
+ // updated to match newValue during dirty-check run
+ var oldValue;
+ // a shallow copy of the newValue from when the last change happened
+ var veryOldValue;
+ // only track veryOldValue if the listener is asking for it
+ var trackVeryOldValue = (listener.length > 1);
+ var changeDetected = 0;
+ var changeDetector = $parse(obj, $watchCollectionInterceptor);
+ var internalArray = [];
+ var internalObject = {};
+ var initRun = true;
+ var oldLength = 0;
+
+ function $watchCollectionInterceptor(_value) {
+ newValue = _value;
+ var newLength, key, bothNaN, newItem, oldItem;
+
+ // If the new value is undefined, then return undefined as the watch may be a one-time watch
+ if (isUndefined(newValue)) return;
+
+ if (!isObject(newValue)) { // if primitive
+ if (oldValue !== newValue) {
+ oldValue = newValue;
+ changeDetected++;
+ }
+ } else if (isArrayLike(newValue)) {
+ if (oldValue !== internalArray) {
+ // we are transitioning from something which was not an array into array.
+ oldValue = internalArray;
+ oldLength = oldValue.length = 0;
+ changeDetected++;
+ }
+
+ newLength = newValue.length;
+
+ if (oldLength !== newLength) {
+ // if lengths do not match we need to trigger change notification
+ changeDetected++;
+ oldValue.length = oldLength = newLength;
+ }
+ // copy the items to oldValue and look for changes.
+ for (var i = 0; i < newLength; i++) {
+ oldItem = oldValue[i];
+ newItem = newValue[i];
+
+ bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
+ if (!bothNaN && (oldItem !== newItem)) {
+ changeDetected++;
+ oldValue[i] = newItem;
+ }
+ }
+ } else {
+ if (oldValue !== internalObject) {
+ // we are transitioning from something which was not an object into object.
+ oldValue = internalObject = {};
+ oldLength = 0;
+ changeDetected++;
+ }
+ // copy the items to oldValue and look for changes.
+ newLength = 0;
+ for (key in newValue) {
+ if (newValue.hasOwnProperty(key)) {
+ newLength++;
+ newItem = newValue[key];
+ oldItem = oldValue[key];
+
+ if (key in oldValue) {
+ bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
+ if (!bothNaN && (oldItem !== newItem)) {
+ changeDetected++;
+ oldValue[key] = newItem;
+ }
+ } else {
+ oldLength++;
+ oldValue[key] = newItem;
+ changeDetected++;
+ }
+ }
+ }
+ if (oldLength > newLength) {
+ // we used to have more keys, need to find them and destroy them.
+ changeDetected++;
+ for (key in oldValue) {
+ if (!newValue.hasOwnProperty(key)) {
+ oldLength--;
+ delete oldValue[key];
+ }
+ }
+ }
+ }
+ return changeDetected;
+ }
+
+ function $watchCollectionAction() {
+ if (initRun) {
+ initRun = false;
+ listener(newValue, newValue, self);
+ } else {
+ listener(newValue, veryOldValue, self);
+ }
+
+ // make a copy for the next time a collection is changed
+ if (trackVeryOldValue) {
+ if (!isObject(newValue)) {
+ //primitive
+ veryOldValue = newValue;
+ } else if (isArrayLike(newValue)) {
+ veryOldValue = new Array(newValue.length);
+ for (var i = 0; i < newValue.length; i++) {
+ veryOldValue[i] = newValue[i];
+ }
+ } else { // if object
+ veryOldValue = {};
+ for (var key in newValue) {
+ if (hasOwnProperty.call(newValue, key)) {
+ veryOldValue[key] = newValue[key];
+ }
+ }
+ }
+ }
+ }
+
+ return this.$watch(changeDetector, $watchCollectionAction);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$digest
+ * @kind function
+ *
+ * @description
+ * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
+ * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
+ * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
+ * until no more listeners are firing. This means that it is possible to get into an infinite
+ * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
+ * iterations exceeds 10.
+ *
+ * Usually, you don't call `$digest()` directly in
+ * {@link ng.directive:ngController controllers} or in
+ * {@link ng.$compileProvider#directive directives}.
+ * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
+ * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.
+ *
+ * If you want to be notified whenever `$digest()` is called,
+ * you can register a `watchExpression` function with
+ * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
+ *
+ * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
+ *
+ * # Example
+ * ```js
+ var scope = ...;
+ scope.name = 'misko';
+ scope.counter = 0;
+
+ expect(scope.counter).toEqual(0);
+ scope.$watch('name', function(newValue, oldValue) {
+ scope.counter = scope.counter + 1;
+ });
+ expect(scope.counter).toEqual(0);
+
+ scope.$digest();
+ // the listener is always called during the first $digest loop after it was registered
+ expect(scope.counter).toEqual(1);
+
+ scope.$digest();
+ // but now it will not be called unless the value changes
+ expect(scope.counter).toEqual(1);
+
+ scope.name = 'adam';
+ scope.$digest();
+ expect(scope.counter).toEqual(2);
+ * ```
+ *
+ */
+ $digest: function() {
+ var watch, value, last,
+ watchers,
+ length,
+ dirty, ttl = TTL,
+ next, current, target = this,
+ watchLog = [],
+ logIdx, logMsg, asyncTask;
+
+ beginPhase('$digest');
+ // Check for changes to browser url that happened in sync before the call to $digest
+ $browser.$$checkUrlChange();
+
+ if (this === $rootScope && applyAsyncId !== null) {
+ // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then
+ // cancel the scheduled $apply and flush the queue of expressions to be evaluated.
+ $browser.defer.cancel(applyAsyncId);
+ flushApplyAsync();
+ }
+
+ lastDirtyWatch = null;
+
+ do { // "while dirty" loop
+ dirty = false;
+ current = target;
+
+ while (asyncQueue.length) {
+ try {
+ asyncTask = asyncQueue.shift();
+ asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ lastDirtyWatch = null;
+ }
+
+ traverseScopesLoop:
+ do { // "traverse the scopes" loop
+ if ((watchers = current.$$watchers)) {
+ // process our watches
+ length = watchers.length;
+ while (length--) {
+ try {
+ watch = watchers[length];
+ // Most common watches are on primitives, in which case we can short
+ // circuit it with === operator, only when === fails do we use .equals
+ if (watch) {
+ if ((value = watch.get(current)) !== (last = watch.last) &&
+ !(watch.eq
+ ? equals(value, last)
+ : (typeof value === 'number' && typeof last === 'number'
+ && isNaN(value) && isNaN(last)))) {
+ dirty = true;
+ lastDirtyWatch = watch;
+ watch.last = watch.eq ? copy(value, null) : value;
+ watch.fn(value, ((last === initWatchVal) ? value : last), current);
+ if (ttl < 5) {
+ logIdx = 4 - ttl;
+ if (!watchLog[logIdx]) watchLog[logIdx] = [];
+ watchLog[logIdx].push({
+ msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
+ newVal: value,
+ oldVal: last
+ });
+ }
+ } else if (watch === lastDirtyWatch) {
+ // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
+ // have already been tested.
+ dirty = false;
+ break traverseScopesLoop;
+ }
+ }
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ }
+
+ // Insanity Warning: scope depth-first traversal
+ // yes, this code is a bit crazy, but it works and we have tests to prove it!
+ // this piece should be kept in sync with the traversal in $broadcast
+ if (!(next = (current.$$childHead ||
+ (current !== target && current.$$nextSibling)))) {
+ while (current !== target && !(next = current.$$nextSibling)) {
+ current = current.$parent;
+ }
+ }
+ } while ((current = next));
+
+ // `break traverseScopesLoop;` takes us to here
+
+ if ((dirty || asyncQueue.length) && !(ttl--)) {
+ clearPhase();
+ throw $rootScopeMinErr('infdig',
+ '{0} $digest() iterations reached. Aborting!\n' +
+ 'Watchers fired in the last 5 iterations: {1}',
+ TTL, watchLog);
+ }
+
+ } while (dirty || asyncQueue.length);
+
+ clearPhase();
+
+ while (postDigestQueue.length) {
+ try {
+ postDigestQueue.shift()();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc event
+ * @name $rootScope.Scope#$destroy
+ * @eventType broadcast on scope being destroyed
+ *
+ * @description
+ * Broadcasted when a scope and its children are being destroyed.
+ *
+ * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
+ * clean up DOM bindings before an element is removed from the DOM.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$destroy
+ * @kind function
+ *
+ * @description
+ * Removes the current scope (and all of its children) from the parent scope. Removal implies
+ * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
+ * propagate to the current scope and its children. Removal also implies that the current
+ * scope is eligible for garbage collection.
+ *
+ * The `$destroy()` is usually used by directives such as
+ * {@link ng.directive:ngRepeat ngRepeat} for managing the
+ * unrolling of the loop.
+ *
+ * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
+ * Application code can register a `$destroy` event handler that will give it a chance to
+ * perform any necessary cleanup.
+ *
+ * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
+ * clean up DOM bindings before an element is removed from the DOM.
+ */
+ $destroy: function() {
+ // we can't destroy the root scope or a scope that has been already destroyed
+ if (this.$$destroyed) return;
+ var parent = this.$parent;
+
+ this.$broadcast('$destroy');
+ this.$$destroyed = true;
+ if (this === $rootScope) return;
+
+ for (var eventName in this.$$listenerCount) {
+ decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
+ }
+
+ // sever all the references to parent scopes (after this cleanup, the current scope should
+ // not be retained by any of our references and should be eligible for garbage collection)
+ if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
+ if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
+ if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
+ if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
+
+ // Disable listeners, watchers and apply/digest methods
+ this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
+ this.$on = this.$watch = this.$watchGroup = function() { return noop; };
+ this.$$listeners = {};
+
+ // All of the code below is bogus code that works around V8's memory leak via optimized code
+ // and inline caches.
+ //
+ // see:
+ // - https://code.google.com/p/v8/issues/detail?id=2073#c26
+ // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
+ // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
+
+ this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
+ this.$$childTail = this.$root = this.$$watchers = null;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$eval
+ * @kind function
+ *
+ * @description
+ * Executes the `expression` on the current scope and returns the result. Any exceptions in
+ * the expression are propagated (uncaught). This is useful when evaluating Angular
+ * expressions.
+ *
+ * # Example
+ * ```js
+ var scope = ng.$rootScope.Scope();
+ scope.a = 1;
+ scope.b = 2;
+
+ expect(scope.$eval('a+b')).toEqual(3);
+ expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
+ * ```
+ *
+ * @param {(string|function())=} expression An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with the current `scope` parameter.
+ *
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
+ * @returns {*} The result of evaluating the expression.
+ */
+ $eval: function(expr, locals) {
+ return $parse(expr)(this, locals);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$evalAsync
+ * @kind function
+ *
+ * @description
+ * Executes the expression on the current scope at a later point in time.
+ *
+ * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
+ * that:
+ *
+ * - it will execute after the function that scheduled the evaluation (preferably before DOM
+ * rendering).
+ * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
+ * `expression` execution.
+ *
+ * Any exceptions from the execution of the expression are forwarded to the
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
+ * will be scheduled. However, it is encouraged to always call code that changes the model
+ * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
+ *
+ * @param {(string|function())=} expression An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with the current `scope` parameter.
+ *
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
+ */
+ $evalAsync: function(expr, locals) {
+ // if we are outside of an $digest loop and this is the first time we are scheduling async
+ // task also schedule async auto-flush
+ if (!$rootScope.$$phase && !asyncQueue.length) {
+ $browser.defer(function() {
+ if (asyncQueue.length) {
+ $rootScope.$digest();
+ }
+ });
+ }
+
+ asyncQueue.push({scope: this, expression: expr, locals: locals});
+ },
+
+ $$postDigest: function(fn) {
+ postDigestQueue.push(fn);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$apply
+ * @kind function
+ *
+ * @description
+ * `$apply()` is used to execute an expression in angular from outside of the angular
+ * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
+ * Because we are calling into the angular framework we need to perform proper scope life
+ * cycle of {@link ng.$exceptionHandler exception handling},
+ * {@link ng.$rootScope.Scope#$digest executing watches}.
+ *
+ * ## Life cycle
+ *
+ * # Pseudo-Code of `$apply()`
+ * ```js
+ function $apply(expr) {
+ try {
+ return $eval(expr);
+ } catch (e) {
+ $exceptionHandler(e);
+ } finally {
+ $root.$digest();
+ }
+ }
+ * ```
+ *
+ *
+ * Scope's `$apply()` method transitions through the following stages:
+ *
+ * 1. The {@link guide/expression expression} is executed using the
+ * {@link ng.$rootScope.Scope#$eval $eval()} method.
+ * 2. Any exceptions from the execution of the expression are forwarded to the
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
+ * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
+ *
+ *
+ * @param {(string|function())=} exp An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with current `scope` parameter.
+ *
+ * @returns {*} The result of evaluating the expression.
+ */
+ $apply: function(expr) {
+ try {
+ beginPhase('$apply');
+ return this.$eval(expr);
+ } catch (e) {
+ $exceptionHandler(e);
+ } finally {
+ clearPhase();
+ try {
+ $rootScope.$digest();
+ } catch (e) {
+ $exceptionHandler(e);
+ throw e;
+ }
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$applyAsync
+ * @kind function
+ *
+ * @description
+ * Schedule the invocation of $apply to occur at a later time. The actual time difference
+ * varies across browsers, but is typically around ~10 milliseconds.
+ *
+ * This can be used to queue up multiple expressions which need to be evaluated in the same
+ * digest.
+ *
+ * @param {(string|function())=} exp An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with current `scope` parameter.
+ */
+ $applyAsync: function(expr) {
+ var scope = this;
+ expr && applyAsyncQueue.push($applyAsyncExpression);
+ scheduleApplyAsync();
+
+ function $applyAsyncExpression() {
+ scope.$eval(expr);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$on
+ * @kind function
+ *
+ * @description
+ * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
+ * discussion of event life cycle.
+ *
+ * The event listener function format is: `function(event, args...)`. The `event` object
+ * passed into the listener has the following attributes:
+ *
+ * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
+ * `$broadcast`-ed.
+ * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the
+ * event propagates through the scope hierarchy, this property is set to null.
+ * - `name` - `{string}`: name of the event.
+ * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
+ * further event propagation (available only for events that were `$emit`-ed).
+ * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
+ * to true.
+ * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
+ *
+ * @param {string} name Event name to listen on.
+ * @param {function(event, ...args)} listener Function to call when the event is emitted.
+ * @returns {function()} Returns a deregistration function for this listener.
+ */
+ $on: function(name, listener) {
+ var namedListeners = this.$$listeners[name];
+ if (!namedListeners) {
+ this.$$listeners[name] = namedListeners = [];
+ }
+ namedListeners.push(listener);
+
+ var current = this;
+ do {
+ if (!current.$$listenerCount[name]) {
+ current.$$listenerCount[name] = 0;
+ }
+ current.$$listenerCount[name]++;
+ } while ((current = current.$parent));
+
+ var self = this;
+ return function() {
+ var indexOfListener = namedListeners.indexOf(listener);
+ if (indexOfListener !== -1) {
+ namedListeners[indexOfListener] = null;
+ decrementListenerCount(self, 1, name);
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$emit
+ * @kind function
+ *
+ * @description
+ * Dispatches an event `name` upwards through the scope hierarchy notifying the
+ * registered {@link ng.$rootScope.Scope#$on} listeners.
+ *
+ * The event life cycle starts at the scope on which `$emit` was called. All
+ * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
+ * notified. Afterwards, the event traverses upwards toward the root scope and calls all
+ * registered listeners along the way. The event will stop propagating if one of the listeners
+ * cancels it.
+ *
+ * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
+ * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * @param {string} name Event name to emit.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
+ * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
+ */
+ $emit: function(name, args) {
+ var empty = [],
+ namedListeners,
+ scope = this,
+ stopPropagation = false,
+ event = {
+ name: name,
+ targetScope: scope,
+ stopPropagation: function() {stopPropagation = true;},
+ preventDefault: function() {
+ event.defaultPrevented = true;
+ },
+ defaultPrevented: false
+ },
+ listenerArgs = concat([event], arguments, 1),
+ i, length;
+
+ do {
+ namedListeners = scope.$$listeners[name] || empty;
+ event.currentScope = scope;
+ for (i = 0, length = namedListeners.length; i < length; i++) {
+
+ // if listeners were deregistered, defragment the array
+ if (!namedListeners[i]) {
+ namedListeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
+ try {
+ //allow all listeners attached to the current scope to run
+ namedListeners[i].apply(null, listenerArgs);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ //if any listener on the current scope stops propagation, prevent bubbling
+ if (stopPropagation) {
+ event.currentScope = null;
+ return event;
+ }
+ //traverse upwards
+ scope = scope.$parent;
+ } while (scope);
+
+ event.currentScope = null;
+
+ return event;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$broadcast
+ * @kind function
+ *
+ * @description
+ * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
+ * registered {@link ng.$rootScope.Scope#$on} listeners.
+ *
+ * The event life cycle starts at the scope on which `$broadcast` was called. All
+ * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
+ * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
+ * scope and calls all registered listeners along the way. The event cannot be canceled.
+ *
+ * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
+ * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * @param {string} name Event name to broadcast.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
+ * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
+ */
+ $broadcast: function(name, args) {
+ var target = this,
+ current = target,
+ next = target,
+ event = {
+ name: name,
+ targetScope: target,
+ preventDefault: function() {
+ event.defaultPrevented = true;
+ },
+ defaultPrevented: false
+ };
+
+ if (!target.$$listenerCount[name]) return event;
+
+ var listenerArgs = concat([event], arguments, 1),
+ listeners, i, length;
+
+ //down while you can, then up and next sibling or up and next sibling until back at root
+ while ((current = next)) {
+ event.currentScope = current;
+ listeners = current.$$listeners[name] || [];
+ for (i = 0, length = listeners.length; i < length; i++) {
+ // if listeners were deregistered, defragment the array
+ if (!listeners[i]) {
+ listeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
+
+ try {
+ listeners[i].apply(null, listenerArgs);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+
+ // Insanity Warning: scope depth-first traversal
+ // yes, this code is a bit crazy, but it works and we have tests to prove it!
+ // this piece should be kept in sync with the traversal in $digest
+ // (though it differs due to having the extra check for $$listenerCount)
+ if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
+ (current !== target && current.$$nextSibling)))) {
+ while (current !== target && !(next = current.$$nextSibling)) {
+ current = current.$parent;
+ }
+ }
+ }
+
+ event.currentScope = null;
+ return event;
+ }
+ };
+
+ var $rootScope = new Scope();
+
+ //The internal queues. Expose them on the $rootScope for debugging/testing purposes.
+ var asyncQueue = $rootScope.$$asyncQueue = [];
+ var postDigestQueue = $rootScope.$$postDigestQueue = [];
+ var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];
+
+ return $rootScope;
+
+
+ function beginPhase(phase) {
+ if ($rootScope.$$phase) {
+ throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
+ }
+
+ $rootScope.$$phase = phase;
+ }
+
+ function clearPhase() {
+ $rootScope.$$phase = null;
+ }
+
+
+ function decrementListenerCount(current, count, name) {
+ do {
+ current.$$listenerCount[name] -= count;
+
+ if (current.$$listenerCount[name] === 0) {
+ delete current.$$listenerCount[name];
+ }
+ } while ((current = current.$parent));
+ }
+
+ /**
+ * function used as an initial value for watchers.
+ * because it's unique we can easily tell it apart from other values
+ */
+ function initWatchVal() {}
+
+ function flushApplyAsync() {
+ while (applyAsyncQueue.length) {
+ try {
+ applyAsyncQueue.shift()();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ applyAsyncId = null;
+ }
+
+ function scheduleApplyAsync() {
+ if (applyAsyncId === null) {
+ applyAsyncId = $browser.defer(function() {
+ $rootScope.$apply(flushApplyAsync);
+ });
+ }
+ }
+ }];
+}
+
+/**
+ * @description
+ * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
+ */
+function $$SanitizeUriProvider() {
+ var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
+ imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/;
+
+ /**
+ * @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;
+ };
+
+
+ /**
+ * @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 = function() {
+ return function sanitizeUri(uri, isImage) {
+ var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
+ var normalizedVal;
+ normalizedVal = urlResolve(uri).href;
+ if (normalizedVal !== '' && !normalizedVal.match(regex)) {
+ return 'unsafe:' + normalizedVal;
+ }
+ return uri;
+ };
+ };
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $sceMinErr = minErr('$sce');
+
+var SCE_CONTEXTS = {
+ HTML: 'html',
+ CSS: 'css',
+ URL: 'url',
+ // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
+ // url. (e.g. ng-include, script src, templateUrl)
+ RESOURCE_URL: 'resourceUrl',
+ JS: 'js'
+};
+
+// Helper functions follow.
+
+function adjustMatcher(matcher) {
+ if (matcher === 'self') {
+ return matcher;
+ } else if (isString(matcher)) {
+ // Strings match exactly except for 2 wildcards - '*' and '**'.
+ // '*' matches any character except those from the set ':/.?&'.
+ // '**' matches any character (like .* in a RegExp).
+ // More than 2 *'s raises an error as it's ill defined.
+ if (matcher.indexOf('***') > -1) {
+ throw $sceMinErr('iwcard',
+ 'Illegal sequence *** in string matcher. String: {0}', matcher);
+ }
+ matcher = escapeForRegexp(matcher).
+ replace('\\*\\*', '.*').
+ replace('\\*', '[^:/.?&;]*');
+ return new RegExp('^' + matcher + '$');
+ } else if (isRegExp(matcher)) {
+ // The only other type of matcher allowed is a Regexp.
+ // Match entire URL / disallow partial matches.
+ // Flags are reset (i.e. no global, ignoreCase or multiline)
+ return new RegExp('^' + matcher.source + '$');
+ } else {
+ throw $sceMinErr('imatcher',
+ 'Matchers may only be "self", string patterns or RegExp objects');
+ }
+}
+
+
+function adjustMatchers(matchers) {
+ var adjustedMatchers = [];
+ if (isDefined(matchers)) {
+ forEach(matchers, function(matcher) {
+ adjustedMatchers.push(adjustMatcher(matcher));
+ });
+ }
+ return adjustedMatchers;
+}
+
+
+/**
+ * @ngdoc service
+ * @name $sceDelegate
+ * @kind function
+ *
+ * @description
+ *
+ * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
+ * Contextual Escaping (SCE)} services to AngularJS.
+ *
+ * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
+ * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
+ * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
+ * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
+ * work because `$sce` delegates to `$sceDelegate` for these operations.
+ *
+ * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
+ *
+ * The default instance of `$sceDelegate` should work out of the box with little pain. While you
+ * can override it completely to change the behavior of `$sce`, the common case would
+ * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
+ * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
+ * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
+ * $sceDelegateProvider.resourceUrlWhitelist} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ */
+
+/**
+ * @ngdoc provider
+ * @name $sceDelegateProvider
+ * @description
+ *
+ * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
+ * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
+ * that the URLs used for sourcing Angular templates are safe. Refer {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
+ * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ *
+ * For the general details about this service in Angular, read the main page for {@link ng.$sce
+ * Strict Contextual Escaping (SCE)}.
+ *
+ * **Example**: Consider the following case. <a name="example"></a>
+ *
+ * - your app is hosted at url `http://myapp.example.com/`
+ * - but some of your templates are hosted on other domains you control such as
+ * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
+ * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
+ *
+ * Here is what a secure configuration for this scenario might look like:
+ *
+ * ```
+ * angular.module('myApp', []).config(function($sceDelegateProvider) {
+ * $sceDelegateProvider.resourceUrlWhitelist([
+ * // Allow same origin resource loads.
+ * 'self',
+ * // Allow loading from our assets domain. Notice the difference between * and **.
+ * 'http://srv*.assets.example.com/**'
+ * ]);
+ *
+ * // The blacklist overrides the whitelist so the open redirect here is blocked.
+ * $sceDelegateProvider.resourceUrlBlacklist([
+ * 'http://myapp.example.com/clickThru**'
+ * ]);
+ * });
+ * ```
+ */
+
+function $SceDelegateProvider() {
+ this.SCE_CONTEXTS = SCE_CONTEXTS;
+
+ // Resource URLs can also be trusted by policy.
+ var resourceUrlWhitelist = ['self'],
+ resourceUrlBlacklist = [];
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegateProvider#resourceUrlWhitelist
+ * @kind function
+ *
+ * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
+ *
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
+ *
+ * Note: **an empty whitelist array will block all URLs**!
+ *
+ * @return {Array} the currently set whitelist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
+ * same origin resource requests.
+ *
+ * @description
+ * Sets/Gets the whitelist of trusted resource URLs.
+ */
+ this.resourceUrlWhitelist = function(value) {
+ if (arguments.length) {
+ resourceUrlWhitelist = adjustMatchers(value);
+ }
+ return resourceUrlWhitelist;
+ };
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegateProvider#resourceUrlBlacklist
+ * @kind function
+ *
+ * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
+ *
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
+ *
+ * The typical usage for the blacklist is to **block
+ * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
+ * these would otherwise be trusted but actually return content from the redirected domain.
+ *
+ * Finally, **the blacklist overrides the whitelist** and has the final say.
+ *
+ * @return {Array} the currently set blacklist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
+ * is no blacklist.)
+ *
+ * @description
+ * Sets/Gets the blacklist of trusted resource URLs.
+ */
+
+ this.resourceUrlBlacklist = function(value) {
+ if (arguments.length) {
+ resourceUrlBlacklist = adjustMatchers(value);
+ }
+ return resourceUrlBlacklist;
+ };
+
+ this.$get = ['$injector', function($injector) {
+
+ var htmlSanitizer = function htmlSanitizer(html) {
+ throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
+ };
+
+ if ($injector.has('$sanitize')) {
+ htmlSanitizer = $injector.get('$sanitize');
+ }
+
+
+ function matchUrl(matcher, parsedUrl) {
+ if (matcher === 'self') {
+ return urlIsSameOrigin(parsedUrl);
+ } else {
+ // definitely a regex. See adjustMatchers()
+ return !!matcher.exec(parsedUrl.href);
+ }
+ }
+
+ function isResourceUrlAllowedByPolicy(url) {
+ var parsedUrl = urlResolve(url.toString());
+ var i, n, allowed = false;
+ // Ensure that at least one item from the whitelist allows this url.
+ for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
+ if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
+ allowed = true;
+ break;
+ }
+ }
+ if (allowed) {
+ // Ensure that no item from the blacklist blocked this url.
+ for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
+ if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
+ allowed = false;
+ break;
+ }
+ }
+ }
+ return allowed;
+ }
+
+ function generateHolderType(Base) {
+ var holderType = function TrustedValueHolderType(trustedValue) {
+ this.$$unwrapTrustedValue = function() {
+ return trustedValue;
+ };
+ };
+ if (Base) {
+ holderType.prototype = new Base();
+ }
+ holderType.prototype.valueOf = function sceValueOf() {
+ return this.$$unwrapTrustedValue();
+ };
+ holderType.prototype.toString = function sceToString() {
+ return this.$$unwrapTrustedValue().toString();
+ };
+ return holderType;
+ }
+
+ var trustedValueHolderBase = generateHolderType(),
+ byType = {};
+
+ byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#trustAs
+ *
+ * @description
+ * Returns an object that is trusted by angular for use in specified strict
+ * contextual escaping contexts (such as ng-bind-html, ng-include, any src
+ * attribute interpolation, any dom event binding attribute interpolation
+ * such as for onclick, etc.) that uses the provided value.
+ * See {@link ng.$sce $sce} for enabling strict contextual escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resourceUrl, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+ function trustAs(type, trustedValue) {
+ var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (!Constructor) {
+ throw $sceMinErr('icontext',
+ 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
+ type, trustedValue);
+ }
+ if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
+ return trustedValue;
+ }
+ // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
+ // mutable objects, we ensure here that the value passed in is actually a string.
+ if (typeof trustedValue !== 'string') {
+ throw $sceMinErr('itype',
+ 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
+ type);
+ }
+ return new Constructor(trustedValue);
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#valueOf
+ *
+ * @description
+ * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
+ *
+ * If the passed parameter is not a value that had been returned by {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
+ *
+ * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
+ * call or anything else.
+ * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
+ * `value` unchanged.
+ */
+ function valueOf(maybeTrusted) {
+ if (maybeTrusted instanceof trustedValueHolderBase) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ } else {
+ return maybeTrusted;
+ }
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#getTrusted
+ *
+ * @description
+ * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
+ * returns the originally supplied value if the queried context type is a supertype of the
+ * created type. If this condition isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} call.
+ * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
+ */
+ function getTrusted(type, maybeTrusted) {
+ if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
+ return maybeTrusted;
+ }
+ var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (constructor && maybeTrusted instanceof constructor) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ }
+ // If we get here, then we may only take one of two actions.
+ // 1. sanitize the value for the requested type, or
+ // 2. throw an exception.
+ if (type === SCE_CONTEXTS.RESOURCE_URL) {
+ if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
+ return maybeTrusted;
+ } else {
+ throw $sceMinErr('insecurl',
+ 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
+ maybeTrusted.toString());
+ }
+ } else if (type === SCE_CONTEXTS.HTML) {
+ return htmlSanitizer(maybeTrusted);
+ }
+ throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
+ }
+
+ return { trustAs: trustAs,
+ getTrusted: getTrusted,
+ valueOf: valueOf };
+ }];
+}
+
+
+/**
+ * @ngdoc provider
+ * @name $sceProvider
+ * @description
+ *
+ * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
+ * - enable/disable Strict Contextual Escaping (SCE) in a module
+ * - override the default implementation with a custom delegate
+ *
+ * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
+ */
+
+/* jshint maxlen: false*/
+
+/**
+ * @ngdoc service
+ * @name $sce
+ * @kind function
+ *
+ * @description
+ *
+ * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
+ *
+ * # Strict Contextual Escaping
+ *
+ * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
+ * contexts to result in a value that is marked as safe to use for that context. One example of
+ * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer
+ * to these contexts as privileged or SCE contexts.
+ *
+ * As of version 1.2, Angular ships with SCE enabled by default.
+ *
+ * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow
+ * one to execute arbitrary javascript by the use of the expression() syntax. Refer
+ * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
+ * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
+ * to the top of your HTML document.
+ *
+ * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
+ * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
+ *
+ * Here's an example of a binding in a privileged context:
+ *
+ * ```
+ * <input ng-model="userHtml">
+ * <div ng-bind-html="userHtml"></div>
+ * ```
+ *
+ * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
+ * disabled, this application allows the user to render arbitrary HTML into the DIV.
+ * In a more realistic example, one may be rendering user comments, blog articles, etc. via
+ * bindings. (HTML is just one example of a context where rendering user controlled input creates
+ * security vulnerabilities.)
+ *
+ * For the case of HTML, you might use a library, either on the client side, or on the server side,
+ * to sanitize unsafe HTML before binding to the value and rendering it in the document.
+ *
+ * How would you ensure that every place that used these types of bindings was bound to a value that
+ * was sanitized by your library (or returned as safe for rendering by your server?) How can you
+ * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
+ * properties/fields and forgot to update the binding to the sanitized value?
+ *
+ * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
+ * determine that something explicitly says it's safe to use a value for binding in that
+ * context. You can then audit your code (a simple grep would do) to ensure that this is only done
+ * for those values that you can easily tell are safe - because they were received from your server,
+ * sanitized by your library, etc. You can organize your codebase to help with this - perhaps
+ * allowing only the files in a specific directory to do this. Ensuring that the internal API
+ * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
+ *
+ * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
+ * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
+ * obtain values that will be accepted by SCE / privileged contexts.
+ *
+ *
+ * ## How does it work?
+ *
+ * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
+ * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
+ * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
+ * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
+ *
+ * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
+ * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
+ * simplified):
+ *
+ * ```
+ * var ngBindHtmlDirective = ['$sce', function($sce) {
+ * return function(scope, element, attr) {
+ * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
+ * element.html(value || '');
+ * });
+ * };
+ * }];
+ * ```
+ *
+ * ## Impact on loading templates
+ *
+ * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
+ * `templateUrl`'s specified by {@link guide/directive directives}.
+ *
+ * By default, Angular only loads templates from the same domain and protocol as the application
+ * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
+ * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
+ * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
+ *
+ * *Please note*:
+ * The browser's
+ * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
+ * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
+ * policy apply in addition to this and may further restrict whether the template is successfully
+ * loaded. This means that without the right CORS policy, loading templates from a different domain
+ * won't work on all browsers. Also, loading templates from `file://` URL does not work on some
+ * browsers.
+ *
+ * ## This feels like too much overhead
+ *
+ * It's important to remember that SCE only applies to interpolation expressions.
+ *
+ * If your expressions are constant literals, they're automatically trusted and you don't need to
+ * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
+ * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
+ *
+ * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
+ * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
+ *
+ * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
+ * templates in `ng-include` from your application's domain without having to even know about SCE.
+ * It blocks loading templates from other domains or loading templates over http from an https
+ * served document. You can change these by setting your own custom {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
+ *
+ * This significantly reduces the overhead. It is far easier to pay the small overhead and have an
+ * application that's secure and can be audited to verify that with much more ease than bolting
+ * security onto an application later.
+ *
+ * <a name="contexts"></a>
+ * ## What trusted context types are supported?
+ *
+ * | Context | Notes |
+ * |---------------------|----------------|
+ * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
+ * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
+ * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
+ * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
+ * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
+ *
+ * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
+ *
+ * Each element in these arrays must be one of the following:
+ *
+ * - **'self'**
+ * - The special **string**, `'self'`, can be used to match against all URLs of the **same
+ * domain** as the application document using the **same protocol**.
+ * - **String** (except the special value `'self'`)
+ * - The string is matched against the full *normalized / absolute URL* of the resource
+ * being tested (substring matches are not good enough.)
+ * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters
+ * match themselves.
+ * - `*`: matches zero or more occurrences of any character other than one of the following 6
+ * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use
+ * in a whitelist.
+ * - `**`: matches zero or more occurrences of *any* character. As such, it's not
+ * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g.
+ * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
+ * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
+ * http://foo.example.com/templates/**).
+ * - **RegExp** (*see caveat below*)
+ * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
+ * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
+ * accidentally introduce a bug when one updates a complex expression (imho, all regexes should
+ * have good test coverage). For instance, the use of `.` in the regex is correct only in a
+ * small number of cases. A `.` character in the regex used when matching the scheme or a
+ * subdomain could be matched against a `:` or literal `.` that was likely not intended. It
+ * is highly recommended to use the string patterns and only fall back to regular expressions
+ * as a last resort.
+ * - The regular expression must be an instance of RegExp (i.e. not a string.) It is
+ * matched against the **entire** *normalized / absolute URL* of the resource being tested
+ * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
+ * present on the RegExp (such as multiline, global, ignoreCase) are ignored.
+ * - If you are generating your JavaScript from some other templating engine (not
+ * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
+ * remember to escape your regular expression (and be aware that you might need more than
+ * one level of escaping depending on your templating engine and the way you interpolated
+ * the value.) Do make use of your platform's escaping mechanism as it might be good
+ * enough before coding your own. E.g. Ruby has
+ * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
+ * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
+ * Javascript lacks a similar built in function for escaping. Take a look at Google
+ * Closure library's [goog.string.regExpEscape(s)](
+ * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
+ *
+ * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
+ *
+ * ## Show me an example using SCE.
+ *
+ * <example module="mySceApp" deps="angular-sanitize.js">
+ * <file name="index.html">
+ * <div ng-controller="AppController as myCtrl">
+ * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
+ * <b>User comments</b><br>
+ * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
+ * $sanitize is available. If $sanitize isn't available, this results in an error instead of an
+ * exploit.
+ * <div class="well">
+ * <div ng-repeat="userComment in myCtrl.userComments">
+ * <b>{{userComment.name}}</b>:
+ * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
+ * <br>
+ * </div>
+ * </div>
+ * </div>
+ * </file>
+ *
+ * <file name="script.js">
+ * angular.module('mySceApp', ['ngSanitize'])
+ * .controller('AppController', ['$http', '$templateCache', '$sce',
+ * function($http, $templateCache, $sce) {
+ * var self = this;
+ * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
+ * self.userComments = userComments;
+ * });
+ * self.explicitlyTrustedHtml = $sce.trustAsHtml(
+ * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
+ * 'sanitization.&quot;">Hover over this text.</span>');
+ * }]);
+ * </file>
+ *
+ * <file name="test_data.json">
+ * [
+ * { "name": "Alice",
+ * "htmlComment":
+ * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
+ * },
+ * { "name": "Bob",
+ * "htmlComment": "<i>Yes!</i> Am I the only other one?"
+ * }
+ * ]
+ * </file>
+ *
+ * <file name="protractor.js" type="protractor">
+ * describe('SCE doc demo', function() {
+ * it('should sanitize untrusted values', function() {
+ * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
+ * .toBe('<span>Is <i>anyone</i> reading this?</span>');
+ * });
+ *
+ * it('should NOT sanitize explicitly trusted values', function() {
+ * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
+ * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
+ * 'sanitization.&quot;">Hover over this text.</span>');
+ * });
+ * });
+ * </file>
+ * </example>
+ *
+ *
+ *
+ * ## Can I disable SCE completely?
+ *
+ * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
+ * for little coding overhead. It will be much harder to take an SCE disabled application and
+ * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
+ * for cases where you have a lot of existing code that was written before SCE was introduced and
+ * you're migrating them a module at a time.
+ *
+ * That said, here's how you can completely disable SCE:
+ *
+ * ```
+ * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
+ * // Completely disable SCE. For demonstration purposes only!
+ * // Do not use in new projects.
+ * $sceProvider.enabled(false);
+ * });
+ * ```
+ *
+ */
+/* jshint maxlen: 100 */
+
+function $SceProvider() {
+ var enabled = true;
+
+ /**
+ * @ngdoc method
+ * @name $sceProvider#enabled
+ * @kind function
+ *
+ * @param {boolean=} value If provided, then enables/disables SCE.
+ * @return {boolean} true if SCE is enabled, false otherwise.
+ *
+ * @description
+ * Enables/disables SCE and returns the current value.
+ */
+ this.enabled = function(value) {
+ if (arguments.length) {
+ enabled = !!value;
+ }
+ return enabled;
+ };
+
+
+ /* Design notes on the default implementation for SCE.
+ *
+ * The API contract for the SCE delegate
+ * -------------------------------------
+ * The SCE delegate object must provide the following 3 methods:
+ *
+ * - trustAs(contextEnum, value)
+ * This method is used to tell the SCE service that the provided value is OK to use in the
+ * contexts specified by contextEnum. It must return an object that will be accepted by
+ * getTrusted() for a compatible contextEnum and return this value.
+ *
+ * - valueOf(value)
+ * For values that were not produced by trustAs(), return them as is. For values that were
+ * produced by trustAs(), return the corresponding input value to trustAs. Basically, if
+ * trustAs is wrapping the given values into some type, this operation unwraps it when given
+ * such a value.
+ *
+ * - getTrusted(contextEnum, value)
+ * This function should return the a value that is safe to use in the context specified by
+ * contextEnum or throw and exception otherwise.
+ *
+ * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
+ * opaque or wrapped in some holder object. That happens to be an implementation detail. For
+ * instance, an implementation could maintain a registry of all trusted objects by context. In
+ * such a case, trustAs() would return the same object that was passed in. getTrusted() would
+ * return the same object passed in if it was found in the registry under a compatible context or
+ * throw an exception otherwise. An implementation might only wrap values some of the time based
+ * on some criteria. getTrusted() might return a value and not throw an exception for special
+ * constants or objects even if not wrapped. All such implementations fulfill this contract.
+ *
+ *
+ * A note on the inheritance model for SCE contexts
+ * ------------------------------------------------
+ * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This
+ * is purely an implementation details.
+ *
+ * The contract is simply this:
+ *
+ * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
+ * will also succeed.
+ *
+ * Inheritance happens to capture this in a natural way. In some future, we
+ * may not use inheritance anymore. That is OK because no code outside of
+ * sce.js and sceSpecs.js would need to be aware of this detail.
+ */
+
+ this.$get = ['$parse', '$sceDelegate', function(
+ $parse, $sceDelegate) {
+ // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow
+ // the "expression(javascript expression)" syntax which is insecure.
+ if (enabled && msie < 8) {
+ throw $sceMinErr('iequirks',
+ 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
+ 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
+ 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
+ }
+
+ var sce = shallowCopy(SCE_CONTEXTS);
+
+ /**
+ * @ngdoc method
+ * @name $sce#isEnabled
+ * @kind function
+ *
+ * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
+ * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
+ *
+ * @description
+ * Returns a boolean indicating if SCE is enabled.
+ */
+ sce.isEnabled = function() {
+ return enabled;
+ };
+ sce.trustAs = $sceDelegate.trustAs;
+ sce.getTrusted = $sceDelegate.getTrusted;
+ sce.valueOf = $sceDelegate.valueOf;
+
+ if (!enabled) {
+ sce.trustAs = sce.getTrusted = function(type, value) { return value; };
+ sce.valueOf = identity;
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAs
+ *
+ * @description
+ * Converts Angular {@link guide/expression expression} into a function. This is like {@link
+ * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
+ * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
+ * *result*)}
+ *
+ * @param {string} type The kind of SCE context in which this result will be used.
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+ sce.parseAs = function sceParseAs(type, expr) {
+ var parsed = $parse(expr);
+ if (parsed.literal && parsed.constant) {
+ return parsed;
+ } else {
+ return $parse(expr, function(value) {
+ return sce.getTrusted(type, value);
+ });
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAs
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
+ * returns an object that is trusted by angular for use in specified strict contextual
+ * escaping contexts (such as ng-bind-html, ng-include, any src attribute
+ * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
+ * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
+ * escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resource_url, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsHtml
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsHtml(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
+ * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsUrl
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsUrl(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
+ * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsResourceUrl(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the return
+ * value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsJs
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsJs(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
+ * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrusted
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
+ * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
+ * originally supplied value if the queried context type is a supertype of the created type.
+ * If this condition isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
+ * call.
+ * @returns {*} The value the was originally provided to
+ * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
+ * Otherwise, throws an exception.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedHtml
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedHtml(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedCss
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedCss(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedUrl
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedUrl(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedResourceUrl(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedJs
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedJs(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsHtml
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsHtml(expression string)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsCss
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsCss(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsUrl
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsUrl(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsResourceUrl(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsJs
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsJs(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ // Shorthand delegations.
+ var parse = sce.parseAs,
+ getTrusted = sce.getTrusted,
+ trustAs = sce.trustAs;
+
+ forEach(SCE_CONTEXTS, function(enumValue, name) {
+ var lName = lowercase(name);
+ sce[camelCase("parse_as_" + lName)] = function(expr) {
+ return parse(enumValue, expr);
+ };
+ sce[camelCase("get_trusted_" + lName)] = function(value) {
+ return getTrusted(enumValue, value);
+ };
+ sce[camelCase("trust_as_" + lName)] = function(value) {
+ return trustAs(enumValue, value);
+ };
+ });
+
+ return sce;
+ }];
+}
+
+/**
+ * !!! This is an undocumented "private" service !!!
+ *
+ * @name $sniffer
+ * @requires $window
+ * @requires $document
+ *
+ * @property {boolean} history Does the browser support html5 history api ?
+ * @property {boolean} transitions Does the browser support CSS transition events ?
+ * @property {boolean} animations Does the browser support CSS animation events ?
+ *
+ * @description
+ * This is very simple implementation of testing browser's features.
+ */
+function $SnifferProvider() {
+ this.$get = ['$window', '$document', function($window, $document) {
+ var eventSupport = {},
+ android =
+ int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
+ boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
+ document = $document[0] || {},
+ vendorPrefix,
+ vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
+ bodyStyle = document.body && document.body.style,
+ transitions = false,
+ animations = false,
+ match;
+
+ if (bodyStyle) {
+ for (var prop in bodyStyle) {
+ if (match = vendorRegex.exec(prop)) {
+ vendorPrefix = match[0];
+ vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
+ break;
+ }
+ }
+
+ if (!vendorPrefix) {
+ vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
+ }
+
+ transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
+ animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
+
+ if (android && (!transitions || !animations)) {
+ transitions = isString(document.body.style.webkitTransition);
+ animations = isString(document.body.style.webkitAnimation);
+ }
+ }
+
+
+ return {
+ // Android has history.pushState, but it does not update location correctly
+ // so let's not use the history API at all.
+ // http://code.google.com/p/android/issues/detail?id=17471
+ // https://github.com/angular/angular.js/issues/904
+
+ // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
+ // so let's not use the history API also
+ // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
+ // jshint -W018
+ history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
+ // jshint +W018
+ hasEvent: function(event) {
+ // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
+ // it. In particular the event is not fired when backspace or delete key are pressed or
+ // when cut operation is performed.
+ // IE10+ implements 'input' event but it erroneously fires under various situations,
+ // e.g. when placeholder changes, or a form is focused.
+ if (event === 'input' && msie <= 11) return false;
+
+ if (isUndefined(eventSupport[event])) {
+ var divElm = document.createElement('div');
+ eventSupport[event] = 'on' + event in divElm;
+ }
+
+ return eventSupport[event];
+ },
+ csp: csp(),
+ vendorPrefix: vendorPrefix,
+ transitions: transitions,
+ animations: animations,
+ android: android
+ };
+ }];
+}
+
+var $compileMinErr = minErr('$compile');
+
+/**
+ * @ngdoc service
+ * @name $templateRequest
+ *
+ * @description
+ * The `$templateRequest` service runs security checks then downloads the provided template using
+ * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
+ * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
+ * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
+ * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
+ * when `tpl` is of type string and `$templateCache` has the matching entry.
+ *
+ * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
+ * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
+ *
+ * @return {Promise} the HTTP Promise for the given.
+ *
+ * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
+ */
+function $TemplateRequestProvider() {
+ this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
+ function handleRequestFn(tpl, ignoreRequestError) {
+ handleRequestFn.totalPendingRequests++;
+
+ // We consider the template cache holds only trusted templates, so
+ // there's no need to go through whitelisting again for keys that already
+ // are included in there. This also makes Angular accept any script
+ // directive, no matter its name. However, we still need to unwrap trusted
+ // types.
+ if (!isString(tpl) || !$templateCache.get(tpl)) {
+ tpl = $sce.getTrustedResourceUrl(tpl);
+ }
+
+ var transformResponse = $http.defaults && $http.defaults.transformResponse;
+
+ if (isArray(transformResponse)) {
+ transformResponse = transformResponse.filter(function(transformer) {
+ return transformer !== defaultHttpResponseTransform;
+ });
+ } else if (transformResponse === defaultHttpResponseTransform) {
+ transformResponse = null;
+ }
+
+ var httpOptions = {
+ cache: $templateCache,
+ transformResponse: transformResponse
+ };
+
+ return $http.get(tpl, httpOptions)
+ ['finally'](function() {
+ handleRequestFn.totalPendingRequests--;
+ })
+ .then(function(response) {
+ return response.data;
+ }, handleError);
+
+ function handleError(resp) {
+ if (!ignoreRequestError) {
+ throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
+ }
+ return $q.reject(resp);
+ }
+ }
+
+ handleRequestFn.totalPendingRequests = 0;
+
+ return handleRequestFn;
+ }];
+}
+
+function $$TestabilityProvider() {
+ this.$get = ['$rootScope', '$browser', '$location',
+ function($rootScope, $browser, $location) {
+
+ /**
+ * @name $testability
+ *
+ * @description
+ * The private $$testability service provides a collection of methods for use when debugging
+ * or by automated test and debugging tools.
+ */
+ var testability = {};
+
+ /**
+ * @name $$testability#findBindings
+ *
+ * @description
+ * Returns an array of elements that are bound (via ng-bind or {{}})
+ * to expressions matching the input.
+ *
+ * @param {Element} element The element root to search from.
+ * @param {string} expression The binding expression to match.
+ * @param {boolean} opt_exactMatch If true, only returns exact matches
+ * for the expression. Filters and whitespace are ignored.
+ */
+ testability.findBindings = function(element, expression, opt_exactMatch) {
+ var bindings = element.getElementsByClassName('ng-binding');
+ var matches = [];
+ forEach(bindings, function(binding) {
+ var dataBinding = angular.element(binding).data('$binding');
+ if (dataBinding) {
+ forEach(dataBinding, function(bindingName) {
+ if (opt_exactMatch) {
+ var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
+ if (matcher.test(bindingName)) {
+ matches.push(binding);
+ }
+ } else {
+ if (bindingName.indexOf(expression) != -1) {
+ matches.push(binding);
+ }
+ }
+ });
+ }
+ });
+ return matches;
+ };
+
+ /**
+ * @name $$testability#findModels
+ *
+ * @description
+ * Returns an array of elements that are two-way found via ng-model to
+ * expressions matching the input.
+ *
+ * @param {Element} element The element root to search from.
+ * @param {string} expression The model expression to match.
+ * @param {boolean} opt_exactMatch If true, only returns exact matches
+ * for the expression.
+ */
+ testability.findModels = function(element, expression, opt_exactMatch) {
+ var prefixes = ['ng-', 'data-ng-', 'ng\\:'];
+ for (var p = 0; p < prefixes.length; ++p) {
+ var attributeEquals = opt_exactMatch ? '=' : '*=';
+ var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]';
+ var elements = element.querySelectorAll(selector);
+ if (elements.length) {
+ return elements;
+ }
+ }
+ };
+
+ /**
+ * @name $$testability#getLocation
+ *
+ * @description
+ * Shortcut for getting the location in a browser agnostic way. Returns
+ * the path, search, and hash. (e.g. /path?a=b#hash)
+ */
+ testability.getLocation = function() {
+ return $location.url();
+ };
+
+ /**
+ * @name $$testability#setLocation
+ *
+ * @description
+ * Shortcut for navigating to a location without doing a full page reload.
+ *
+ * @param {string} url The location url (path, search and hash,
+ * e.g. /path?a=b#hash) to go to.
+ */
+ testability.setLocation = function(url) {
+ if (url !== $location.url()) {
+ $location.url(url);
+ $rootScope.$digest();
+ }
+ };
+
+ /**
+ * @name $$testability#whenStable
+ *
+ * @description
+ * Calls the callback when $timeout and $http requests are completed.
+ *
+ * @param {function} callback
+ */
+ testability.whenStable = function(callback) {
+ $browser.notifyWhenNoOutstandingRequests(callback);
+ };
+
+ return testability;
+ }];
+}
+
+function $TimeoutProvider() {
+ this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
+ function($rootScope, $browser, $q, $$q, $exceptionHandler) {
+ var deferreds = {};
+
+
+ /**
+ * @ngdoc service
+ * @name $timeout
+ *
+ * @description
+ * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
+ * block and delegates any exceptions to
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * The return value of registering a timeout function is a promise, which will be resolved when
+ * the timeout is reached and the timeout function is executed.
+ *
+ * To cancel a timeout request, call `$timeout.cancel(promise)`.
+ *
+ * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
+ * synchronously flush the queue of deferred functions.
+ *
+ * @param {function()} fn A function, whose execution should be delayed.
+ * @param {number=} [delay=0] Delay in milliseconds.
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
+ * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
+ * promise will be resolved with is the return value of the `fn` function.
+ *
+ */
+ function timeout(fn, delay, invokeApply) {
+ var skipApply = (isDefined(invokeApply) && !invokeApply),
+ deferred = (skipApply ? $$q : $q).defer(),
+ promise = deferred.promise,
+ timeoutId;
+
+ timeoutId = $browser.defer(function() {
+ try {
+ deferred.resolve(fn());
+ } catch (e) {
+ deferred.reject(e);
+ $exceptionHandler(e);
+ }
+ finally {
+ delete deferreds[promise.$$timeoutId];
+ }
+
+ if (!skipApply) $rootScope.$apply();
+ }, delay);
+
+ promise.$$timeoutId = timeoutId;
+ deferreds[timeoutId] = deferred;
+
+ return promise;
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $timeout#cancel
+ *
+ * @description
+ * Cancels a task associated with the `promise`. As a result of this, the promise will be
+ * resolved with a rejection.
+ *
+ * @param {Promise=} promise Promise returned by the `$timeout` function.
+ * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
+ * canceled.
+ */
+ timeout.cancel = function(promise) {
+ if (promise && promise.$$timeoutId in deferreds) {
+ deferreds[promise.$$timeoutId].reject('canceled');
+ delete deferreds[promise.$$timeoutId];
+ return $browser.defer.cancel(promise.$$timeoutId);
+ }
+ return false;
+ };
+
+ return timeout;
+ }];
+}
+
+// NOTE: The usage of window and document instead of $window and $document here is
+// deliberate. This service depends on the specific behavior of anchor nodes created by the
+// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
+// cause us to break tests. In addition, when the browser resolves a URL for XHR, it
+// doesn't know about mocked locations and resolves URLs to the real document - which is
+// exactly the behavior needed here. There is little value is mocking these out for this
+// service.
+var urlParsingNode = document.createElement("a");
+var originUrl = urlResolve(window.location.href);
+
+
+/**
+ *
+ * Implementation Notes for non-IE browsers
+ * ----------------------------------------
+ * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
+ * results both in the normalizing and parsing of the URL. Normalizing means that a relative
+ * URL will be resolved into an absolute URL in the context of the application document.
+ * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
+ * properties are all populated to reflect the normalized URL. This approach has wide
+ * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
+ * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
+ *
+ * Implementation Notes for IE
+ * ---------------------------
+ * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
+ * browsers. However, the parsed components will not be set if the URL assigned did not specify
+ * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
+ * work around that by performing the parsing in a 2nd step by taking a previously normalized
+ * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
+ * properties such as protocol, hostname, port, etc.
+ *
+ * References:
+ * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
+ * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
+ * http://url.spec.whatwg.org/#urlutils
+ * https://github.com/angular/angular.js/pull/2902
+ * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
+ *
+ * @kind function
+ * @param {string} url The URL to be parsed.
+ * @description Normalizes and parses a URL.
+ * @returns {object} Returns the normalized URL as a dictionary.
+ *
+ * | member name | Description |
+ * |---------------|----------------|
+ * | href | A normalized version of the provided URL if it was not an absolute URL |
+ * | protocol | The protocol including the trailing colon |
+ * | host | The host and port (if the port is non-default) of the normalizedUrl |
+ * | search | The search params, minus the question mark |
+ * | hash | The hash string, minus the hash symbol
+ * | hostname | The hostname
+ * | port | The port, without ":"
+ * | pathname | The pathname, beginning with "/"
+ *
+ */
+function urlResolve(url) {
+ var href = url;
+
+ if (msie) {
+ // Normalize before parse. Refer Implementation Notes on why this is
+ // done in two steps on IE.
+ urlParsingNode.setAttribute("href", href);
+ href = urlParsingNode.href;
+ }
+
+ urlParsingNode.setAttribute('href', href);
+
+ // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
+ return {
+ href: urlParsingNode.href,
+ protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
+ host: urlParsingNode.host,
+ search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
+ hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
+ hostname: urlParsingNode.hostname,
+ port: urlParsingNode.port,
+ pathname: (urlParsingNode.pathname.charAt(0) === '/')
+ ? urlParsingNode.pathname
+ : '/' + urlParsingNode.pathname
+ };
+}
+
+/**
+ * Parse a request URL and determine whether this is a same-origin request as the application document.
+ *
+ * @param {string|object} requestUrl The url of the request as a string that will be resolved
+ * or a parsed URL object.
+ * @returns {boolean} Whether the request is for the same origin as the application document.
+ */
+function urlIsSameOrigin(requestUrl) {
+ var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
+ return (parsed.protocol === originUrl.protocol &&
+ parsed.host === originUrl.host);
+}
+
+/**
+ * @ngdoc service
+ * @name $window
+ *
+ * @description
+ * A reference to the browser's `window` object. While `window`
+ * is globally available in JavaScript, it causes testability problems, because
+ * it is a global variable. In angular we always refer to it through the
+ * `$window` service, so it may be overridden, removed or mocked for testing.
+ *
+ * Expressions, like the one defined for the `ngClick` directive in the example
+ * below, are evaluated with respect to the current scope. Therefore, there is
+ * no risk of inadvertently coding in a dependency on a global value in such an
+ * expression.
+ *
+ * @example
+ <example module="windowExample">
+ <file name="index.html">
+ <script>
+ angular.module('windowExample', [])
+ .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
+ $scope.greeting = 'Hello, World!';
+ $scope.doGreeting = function(greeting) {
+ $window.alert(greeting);
+ };
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input type="text" ng-model="greeting" />
+ <button ng-click="doGreeting(greeting)">ALERT</button>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should display the greeting in the input box', function() {
+ element(by.model('greeting')).sendKeys('Hello, E2E Tests');
+ // If we click the button it will block the test runner
+ // element(':button').click();
+ });
+ </file>
+ </example>
+ */
+function $WindowProvider() {
+ this.$get = valueFn(window);
+}
+
+/* global currencyFilter: true,
+ dateFilter: true,
+ filterFilter: true,
+ jsonFilter: true,
+ limitToFilter: true,
+ lowercaseFilter: true,
+ numberFilter: true,
+ orderByFilter: true,
+ uppercaseFilter: true,
+ */
+
+/**
+ * @ngdoc provider
+ * @name $filterProvider
+ * @description
+ *
+ * Filters are just functions which transform input to an output. However filters need to be
+ * Dependency Injected. To achieve this a filter definition consists of a factory function which is
+ * annotated with dependencies and is responsible for creating a filter function.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ *
+ * ```js
+ * // Filter registration
+ * function MyModule($provide, $filterProvider) {
+ * // create a service to demonstrate injection (not always needed)
+ * $provide.value('greet', function(name){
+ * return 'Hello ' + name + '!';
+ * });
+ *
+ * // register a filter factory which uses the
+ * // greet service to demonstrate DI.
+ * $filterProvider.register('greet', function(greet){
+ * // return the filter function which uses the greet service
+ * // to generate salutation
+ * return function(text) {
+ * // filters need to be forgiving so check input validity
+ * return text && greet(text) || text;
+ * };
+ * });
+ * }
+ * ```
+ *
+ * The filter function is registered with the `$injector` under the filter name suffix with
+ * `Filter`.
+ *
+ * ```js
+ * it('should be the same instance', inject(
+ * function($filterProvider) {
+ * $filterProvider.register('reverse', function(){
+ * return ...;
+ * });
+ * },
+ * function($filter, reverseFilter) {
+ * expect($filter('reverse')).toBe(reverseFilter);
+ * });
+ * ```
+ *
+ *
+ * For more information about how angular filters work, and how to create your own filters, see
+ * {@link guide/filter Filters} in the Angular Developer Guide.
+ */
+
+/**
+ * @ngdoc service
+ * @name $filter
+ * @kind function
+ * @description
+ * Filters are used for formatting data displayed to the user.
+ *
+ * The general syntax in templates is as follows:
+ *
+ * {{ expression [| filter_name[:parameter_value] ... ] }}
+ *
+ * @param {String} name Name of the filter function to retrieve
+ * @return {Function} the filter function
+ * @example
+ <example name="$filter" module="filterExample">
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <h3>{{ originalText }}</h3>
+ <h3>{{ filteredText }}</h3>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('filterExample', [])
+ .controller('MainCtrl', function($scope, $filter) {
+ $scope.originalText = 'hello';
+ $scope.filteredText = $filter('uppercase')($scope.originalText);
+ });
+ </file>
+ </example>
+ */
+$FilterProvider.$inject = ['$provide'];
+function $FilterProvider($provide) {
+ var suffix = 'Filter';
+
+ /**
+ * @ngdoc method
+ * @name $filterProvider#register
+ * @param {string|Object} name Name of the filter function, or an object map of filters where
+ * the keys are the filter names and the values are the filter factories.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
+ * of the registered filter instances.
+ */
+ function register(name, factory) {
+ if (isObject(name)) {
+ var filters = {};
+ forEach(name, function(filter, key) {
+ filters[key] = register(key, filter);
+ });
+ return filters;
+ } else {
+ return $provide.factory(name + suffix, factory);
+ }
+ }
+ this.register = register;
+
+ this.$get = ['$injector', function($injector) {
+ return function(name) {
+ return $injector.get(name + suffix);
+ };
+ }];
+
+ ////////////////////////////////////////
+
+ /* global
+ currencyFilter: false,
+ dateFilter: false,
+ filterFilter: false,
+ jsonFilter: false,
+ limitToFilter: false,
+ lowercaseFilter: false,
+ numberFilter: false,
+ orderByFilter: false,
+ uppercaseFilter: false,
+ */
+
+ register('currency', currencyFilter);
+ register('date', dateFilter);
+ register('filter', filterFilter);
+ register('json', jsonFilter);
+ register('limitTo', limitToFilter);
+ register('lowercase', lowercaseFilter);
+ register('number', numberFilter);
+ register('orderBy', orderByFilter);
+ register('uppercase', uppercaseFilter);
+}
+
+/**
+ * @ngdoc filter
+ * @name filter
+ * @kind function
+ *
+ * @description
+ * Selects a subset of items from `array` and returns it as a new array.
+ *
+ * @param {Array} array The source array.
+ * @param {string|Object|function()} expression The predicate to be used for selecting items from
+ * `array`.
+ *
+ * Can be one of:
+ *
+ * - `string`: The string is used for matching against the contents of the `array`. All strings or
+ * objects with string properties in `array` that match this string will be returned. This also
+ * applies to nested object properties.
+ * The predicate can be negated by prefixing the string with `!`.
+ *
+ * - `Object`: A pattern object can be used to filter specific properties on objects contained
+ * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
+ * which have property `name` containing "M" and property `phone` containing "1". A special
+ * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
+ * property of the object or its nested object properties. That's equivalent to the simple
+ * substring match with a `string` as described above. The predicate can be negated by prefixing
+ * the string with `!`.
+ * For example `{name: "!M"}` predicate will return an array of items which have property `name`
+ * not containing "M".
+ *
+ * Note that a named property will match properties on the same level only, while the special
+ * `$` property will match properties on the same level or deeper. E.g. an array item like
+ * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
+ * **will** be matched by `{$: 'John'}`.
+ *
+ * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
+ * function is called for each element of `array`. The final result is an array of those
+ * elements that the predicate returned true for.
+ *
+ * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
+ * determining if the expected value (from the filter expression) and actual value (from
+ * the object in the array) should be considered a match.
+ *
+ * Can be one of:
+ *
+ * - `function(actual, expected)`:
+ * The function will be given the object value and the predicate value to compare and
+ * should return true if both values should be considered equal.
+ *
+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
+ * This is essentially strict comparison of expected and actual.
+ *
+ * - `false|undefined`: A short hand for a function which will look for a substring match in case
+ * insensitive way.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div ng-init="friends = [{name:'John', phone:'555-1276'},
+ {name:'Mary', phone:'800-BIG-MARY'},
+ {name:'Mike', phone:'555-4321'},
+ {name:'Adam', phone:'555-5678'},
+ {name:'Julie', phone:'555-8765'},
+ {name:'Juliette', phone:'555-5678'}]"></div>
+
+ Search: <input ng-model="searchText">
+ <table id="searchTextResults">
+ <tr><th>Name</th><th>Phone</th></tr>
+ <tr ng-repeat="friend in friends | filter:searchText">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ </tr>
+ </table>
+ <hr>
+ Any: <input ng-model="search.$"> <br>
+ Name only <input ng-model="search.name"><br>
+ Phone only <input ng-model="search.phone"><br>
+ Equality <input type="checkbox" ng-model="strict"><br>
+ <table id="searchObjResults">
+ <tr><th>Name</th><th>Phone</th></tr>
+ <tr ng-repeat="friendObj in friends | filter:search:strict">
+ <td>{{friendObj.name}}</td>
+ <td>{{friendObj.phone}}</td>
+ </tr>
+ </table>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var expectFriendNames = function(expectedNames, key) {
+ element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
+ arr.forEach(function(wd, i) {
+ expect(wd.getText()).toMatch(expectedNames[i]);
+ });
+ });
+ };
+
+ it('should search across all fields when filtering with a string', function() {
+ var searchText = element(by.model('searchText'));
+ searchText.clear();
+ searchText.sendKeys('m');
+ expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
+
+ searchText.clear();
+ searchText.sendKeys('76');
+ expectFriendNames(['John', 'Julie'], 'friend');
+ });
+
+ it('should search in specific fields when filtering with a predicate object', function() {
+ var searchAny = element(by.model('search.$'));
+ searchAny.clear();
+ searchAny.sendKeys('i');
+ expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
+ });
+ it('should use a equal comparison when comparator is true', function() {
+ var searchName = element(by.model('search.name'));
+ var strict = element(by.model('strict'));
+ searchName.clear();
+ searchName.sendKeys('Julie');
+ strict.click();
+ expectFriendNames(['Julie'], 'friendObj');
+ });
+ </file>
+ </example>
+ */
+function filterFilter() {
+ return function(array, expression, comparator) {
+ if (!isArray(array)) return array;
+
+ var expressionType = (expression !== null) ? typeof expression : 'null';
+ var predicateFn;
+ var matchAgainstAnyProp;
+
+ switch (expressionType) {
+ case 'function':
+ predicateFn = expression;
+ break;
+ case 'boolean':
+ case 'null':
+ case 'number':
+ case 'string':
+ matchAgainstAnyProp = true;
+ //jshint -W086
+ case 'object':
+ //jshint +W086
+ predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
+ break;
+ default:
+ return array;
+ }
+
+ return array.filter(predicateFn);
+ };
+}
+
+// Helper functions for `filterFilter`
+function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
+ var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
+ var predicateFn;
+
+ if (comparator === true) {
+ comparator = equals;
+ } else if (!isFunction(comparator)) {
+ comparator = function(actual, expected) {
+ if (isUndefined(actual)) {
+ // No substring matching against `undefined`
+ return false;
+ }
+ if ((actual === null) || (expected === null)) {
+ // No substring matching against `null`; only match against `null`
+ return actual === expected;
+ }
+ if (isObject(actual) || isObject(expected)) {
+ // Prevent an object to be considered equal to a string like `'[object'`
+ return false;
+ }
+
+ actual = lowercase('' + actual);
+ expected = lowercase('' + expected);
+ return actual.indexOf(expected) !== -1;
+ };
+ }
+
+ predicateFn = function(item) {
+ if (shouldMatchPrimitives && !isObject(item)) {
+ return deepCompare(item, expression.$, comparator, false);
+ }
+ return deepCompare(item, expression, comparator, matchAgainstAnyProp);
+ };
+
+ return predicateFn;
+}
+
+function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
+ var actualType = (actual !== null) ? typeof actual : 'null';
+ var expectedType = (expected !== null) ? typeof expected : 'null';
+
+ if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
+ return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
+ } else if (isArray(actual)) {
+ // In case `actual` is an array, consider it a match
+ // if ANY of it's items matches `expected`
+ return actual.some(function(item) {
+ return deepCompare(item, expected, comparator, matchAgainstAnyProp);
+ });
+ }
+
+ switch (actualType) {
+ case 'object':
+ var key;
+ if (matchAgainstAnyProp) {
+ for (key in actual) {
+ if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
+ return true;
+ }
+ }
+ return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
+ } else if (expectedType === 'object') {
+ for (key in expected) {
+ var expectedVal = expected[key];
+ if (isFunction(expectedVal) || isUndefined(expectedVal)) {
+ continue;
+ }
+
+ var matchAnyProperty = key === '$';
+ var actualVal = matchAnyProperty ? actual : actual[key];
+ if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return comparator(actual, expected);
+ }
+ break;
+ case 'function':
+ return false;
+ default:
+ return comparator(actual, expected);
+ }
+}
+
+/**
+ * @ngdoc filter
+ * @name currency
+ * @kind function
+ *
+ * @description
+ * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
+ * symbol for current locale is used.
+ *
+ * @param {number} amount Input to filter.
+ * @param {string=} symbol Currency symbol or identifier to be displayed.
+ * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale
+ * @returns {string} Formatted number.
+ *
+ *
+ * @example
+ <example module="currencyExample">
+ <file name="index.html">
+ <script>
+ angular.module('currencyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.amount = 1234.56;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input type="number" ng-model="amount"> <br>
+ default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
+ custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span>
+ no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should init with 1234.56', function() {
+ expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
+ expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');
+ expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');
+ });
+ it('should update', function() {
+ if (browser.params.browser == 'safari') {
+ // Safari does not understand the minus key. See
+ // https://github.com/angular/protractor/issues/481
+ return;
+ }
+ element(by.model('amount')).clear();
+ element(by.model('amount')).sendKeys('-1234');
+ expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
+ expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');
+ expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');
+ });
+ </file>
+ </example>
+ */
+currencyFilter.$inject = ['$locale'];
+function currencyFilter($locale) {
+ var formats = $locale.NUMBER_FORMATS;
+ return function(amount, currencySymbol, fractionSize) {
+ if (isUndefined(currencySymbol)) {
+ currencySymbol = formats.CURRENCY_SYM;
+ }
+
+ if (isUndefined(fractionSize)) {
+ fractionSize = formats.PATTERNS[1].maxFrac;
+ }
+
+ // if null or undefined pass it through
+ return (amount == null)
+ ? amount
+ : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
+ replace(/\u00A4/g, currencySymbol);
+ };
+}
+
+/**
+ * @ngdoc filter
+ * @name number
+ * @kind function
+ *
+ * @description
+ * Formats a number as text.
+ *
+ * If the input is null or undefined, it will just be returned.
+ * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
+ * If the input is not a number an empty string is returned.
+ *
+ * @param {number|string} number Number to format.
+ * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
+ * If this is not provided then the fraction size is computed from the current locale's number
+ * formatting pattern. In the case of the default locale, it will be 3.
+ * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
+ *
+ * @example
+ <example module="numberFilterExample">
+ <file name="index.html">
+ <script>
+ angular.module('numberFilterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = 1234.56789;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Enter number: <input ng-model='val'><br>
+ Default formatting: <span id='number-default'>{{val | number}}</span><br>
+ No fractions: <span>{{val | number:0}}</span><br>
+ Negative number: <span>{{-val | number:4}}</span>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should format numbers', function() {
+ expect(element(by.id('number-default')).getText()).toBe('1,234.568');
+ expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
+ });
+
+ it('should update', function() {
+ element(by.model('val')).clear();
+ element(by.model('val')).sendKeys('3374.333');
+ expect(element(by.id('number-default')).getText()).toBe('3,374.333');
+ expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
+ });
+ </file>
+ </example>
+ */
+
+
+numberFilter.$inject = ['$locale'];
+function numberFilter($locale) {
+ var formats = $locale.NUMBER_FORMATS;
+ return function(number, fractionSize) {
+
+ // if null or undefined pass it through
+ return (number == null)
+ ? number
+ : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
+ fractionSize);
+ };
+}
+
+var DECIMAL_SEP = '.';
+function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
+ if (!isFinite(number) || isObject(number)) return '';
+
+ var isNegative = number < 0;
+ number = Math.abs(number);
+ var numStr = number + '',
+ formatedText = '',
+ parts = [];
+
+ var hasExponent = false;
+ if (numStr.indexOf('e') !== -1) {
+ var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
+ if (match && match[2] == '-' && match[3] > fractionSize + 1) {
+ number = 0;
+ } else {
+ formatedText = numStr;
+ hasExponent = true;
+ }
+ }
+
+ if (!hasExponent) {
+ var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
+
+ // determine fractionSize if it is not specified
+ if (isUndefined(fractionSize)) {
+ fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
+ }
+
+ // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
+ // inspired by:
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
+ number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
+
+ var fraction = ('' + number).split(DECIMAL_SEP);
+ var whole = fraction[0];
+ fraction = fraction[1] || '';
+
+ var i, pos = 0,
+ lgroup = pattern.lgSize,
+ group = pattern.gSize;
+
+ if (whole.length >= (lgroup + group)) {
+ pos = whole.length - lgroup;
+ for (i = 0; i < pos; i++) {
+ if ((pos - i) % group === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
+ }
+ }
+
+ for (i = pos; i < whole.length; i++) {
+ if ((whole.length - i) % lgroup === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
+ }
+
+ // format fraction part.
+ while (fraction.length < fractionSize) {
+ fraction += '0';
+ }
+
+ if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
+ } else {
+ if (fractionSize > 0 && number < 1) {
+ formatedText = number.toFixed(fractionSize);
+ number = parseFloat(formatedText);
+ }
+ }
+
+ if (number === 0) {
+ isNegative = false;
+ }
+
+ parts.push(isNegative ? pattern.negPre : pattern.posPre,
+ formatedText,
+ isNegative ? pattern.negSuf : pattern.posSuf);
+ return parts.join('');
+}
+
+function padNumber(num, digits, trim) {
+ var neg = '';
+ if (num < 0) {
+ neg = '-';
+ num = -num;
+ }
+ num = '' + num;
+ while (num.length < digits) num = '0' + num;
+ if (trim)
+ num = num.substr(num.length - digits);
+ return neg + num;
+}
+
+
+function dateGetter(name, size, offset, trim) {
+ offset = offset || 0;
+ return function(date) {
+ var value = date['get' + name]();
+ if (offset > 0 || value > -offset)
+ value += offset;
+ if (value === 0 && offset == -12) value = 12;
+ return padNumber(value, size, trim);
+ };
+}
+
+function dateStrGetter(name, shortForm) {
+ return function(date, formats) {
+ var value = date['get' + name]();
+ var get = uppercase(shortForm ? ('SHORT' + name) : name);
+
+ return formats[get][value];
+ };
+}
+
+function timeZoneGetter(date) {
+ var zone = -1 * date.getTimezoneOffset();
+ var paddedZone = (zone >= 0) ? "+" : "";
+
+ paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
+ padNumber(Math.abs(zone % 60), 2);
+
+ return paddedZone;
+}
+
+function getFirstThursdayOfYear(year) {
+ // 0 = index of January
+ var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
+ // 4 = index of Thursday (+1 to account for 1st = 5)
+ // 11 = index of *next* Thursday (+1 account for 1st = 12)
+ return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
+}
+
+function getThursdayThisWeek(datetime) {
+ return new Date(datetime.getFullYear(), datetime.getMonth(),
+ // 4 = index of Thursday
+ datetime.getDate() + (4 - datetime.getDay()));
+}
+
+function weekGetter(size) {
+ return function(date) {
+ var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
+ thisThurs = getThursdayThisWeek(date);
+
+ var diff = +thisThurs - +firstThurs,
+ result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
+
+ return padNumber(result, size);
+ };
+}
+
+function ampmGetter(date, formats) {
+ return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
+}
+
+function eraGetter(date, formats) {
+ return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
+}
+
+function longEraGetter(date, formats) {
+ return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
+}
+
+var DATE_FORMATS = {
+ yyyy: dateGetter('FullYear', 4),
+ yy: dateGetter('FullYear', 2, 0, true),
+ y: dateGetter('FullYear', 1),
+ MMMM: dateStrGetter('Month'),
+ MMM: dateStrGetter('Month', true),
+ MM: dateGetter('Month', 2, 1),
+ M: dateGetter('Month', 1, 1),
+ dd: dateGetter('Date', 2),
+ d: dateGetter('Date', 1),
+ HH: dateGetter('Hours', 2),
+ H: dateGetter('Hours', 1),
+ hh: dateGetter('Hours', 2, -12),
+ h: dateGetter('Hours', 1, -12),
+ mm: dateGetter('Minutes', 2),
+ m: dateGetter('Minutes', 1),
+ ss: dateGetter('Seconds', 2),
+ s: dateGetter('Seconds', 1),
+ // while ISO 8601 requires fractions to be prefixed with `.` or `,`
+ // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
+ sss: dateGetter('Milliseconds', 3),
+ EEEE: dateStrGetter('Day'),
+ EEE: dateStrGetter('Day', true),
+ a: ampmGetter,
+ Z: timeZoneGetter,
+ ww: weekGetter(2),
+ w: weekGetter(1),
+ G: eraGetter,
+ GG: eraGetter,
+ GGG: eraGetter,
+ GGGG: longEraGetter
+};
+
+var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
+ NUMBER_STRING = /^\-?\d+$/;
+
+/**
+ * @ngdoc filter
+ * @name date
+ * @kind function
+ *
+ * @description
+ * Formats `date` to a string based on the requested `format`.
+ *
+ * `format` string can be composed of the following elements:
+ *
+ * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
+ * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
+ * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
+ * * `'MMMM'`: Month in year (January-December)
+ * * `'MMM'`: Month in year (Jan-Dec)
+ * * `'MM'`: Month in year, padded (01-12)
+ * * `'M'`: Month in year (1-12)
+ * * `'dd'`: Day in month, padded (01-31)
+ * * `'d'`: Day in month (1-31)
+ * * `'EEEE'`: Day in Week,(Sunday-Saturday)
+ * * `'EEE'`: Day in Week, (Sun-Sat)
+ * * `'HH'`: Hour in day, padded (00-23)
+ * * `'H'`: Hour in day (0-23)
+ * * `'hh'`: Hour in AM/PM, padded (01-12)
+ * * `'h'`: Hour in AM/PM, (1-12)
+ * * `'mm'`: Minute in hour, padded (00-59)
+ * * `'m'`: Minute in hour (0-59)
+ * * `'ss'`: Second in minute, padded (00-59)
+ * * `'s'`: Second in minute (0-59)
+ * * `'sss'`: Millisecond in second, padded (000-999)
+ * * `'a'`: AM/PM marker
+ * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
+ * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
+ * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
+ * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
+ * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
+ *
+ * `format` string can also be one of the following predefined
+ * {@link guide/i18n localizable formats}:
+ *
+ * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
+ * (e.g. Sep 3, 2010 12:05:08 PM)
+ * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM)
+ * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale
+ * (e.g. Friday, September 3, 2010)
+ * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
+ * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
+ * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
+ * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)
+ * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)
+ *
+ * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
+ * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
+ * (e.g. `"h 'o''clock'"`).
+ *
+ * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
+ * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
+ * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
+ * specified in the string input, the time is considered to be in the local timezone.
+ * @param {string=} format Formatting rules (see Description). If not specified,
+ * `mediumDate` is used.
+ * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.
+ * If not specified, the timezone of the browser will be used.
+ * @returns {string} Formatted string or the input if input is not recognized as date/millis.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
+ <span>{{1288323623006 | date:'medium'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
+ <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
+ <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
+ <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should format date', function() {
+ expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
+ toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
+ expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
+ toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
+ expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
+ toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
+ expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
+ toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
+ });
+ </file>
+ </example>
+ */
+dateFilter.$inject = ['$locale'];
+function dateFilter($locale) {
+
+
+ var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
+ // 1 2 3 4 5 6 7 8 9 10 11
+ function jsonStringToDate(string) {
+ var match;
+ if (match = string.match(R_ISO8601_STR)) {
+ var date = new Date(0),
+ tzHour = 0,
+ tzMin = 0,
+ dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
+ timeSetter = match[8] ? date.setUTCHours : date.setHours;
+
+ if (match[9]) {
+ tzHour = int(match[9] + match[10]);
+ tzMin = int(match[9] + match[11]);
+ }
+ dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
+ var h = int(match[4] || 0) - tzHour;
+ var m = int(match[5] || 0) - tzMin;
+ var s = int(match[6] || 0);
+ var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
+ timeSetter.call(date, h, m, s, ms);
+ return date;
+ }
+ return string;
+ }
+
+
+ return function(date, format, timezone) {
+ var text = '',
+ parts = [],
+ fn, match;
+
+ format = format || 'mediumDate';
+ format = $locale.DATETIME_FORMATS[format] || format;
+ if (isString(date)) {
+ date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);
+ }
+
+ if (isNumber(date)) {
+ date = new Date(date);
+ }
+
+ if (!isDate(date)) {
+ return date;
+ }
+
+ while (format) {
+ match = DATE_FORMATS_SPLIT.exec(format);
+ if (match) {
+ parts = concat(parts, match, 1);
+ format = parts.pop();
+ } else {
+ parts.push(format);
+ format = null;
+ }
+ }
+
+ if (timezone && timezone === 'UTC') {
+ date = new Date(date.getTime());
+ date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
+ }
+ forEach(parts, function(value) {
+ fn = DATE_FORMATS[value];
+ text += fn ? fn(date, $locale.DATETIME_FORMATS)
+ : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
+ });
+
+ return text;
+ };
+}
+
+
+/**
+ * @ngdoc filter
+ * @name json
+ * @kind function
+ *
+ * @description
+ * Allows you to convert a JavaScript object into JSON string.
+ *
+ * This filter is mostly useful for debugging. When using the double curly {{value}} notation
+ * the binding is automatically converted to JSON.
+ *
+ * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
+ * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
+ * @returns {string} JSON string.
+ *
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
+ <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should jsonify filtered objects', function() {
+ expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
+ expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
+ });
+ </file>
+ </example>
+ *
+ */
+function jsonFilter() {
+ return function(object, spacing) {
+ if (isUndefined(spacing)) {
+ spacing = 2;
+ }
+ return toJson(object, spacing);
+ };
+}
+
+
+/**
+ * @ngdoc filter
+ * @name lowercase
+ * @kind function
+ * @description
+ * Converts string to lowercase.
+ * @see angular.lowercase
+ */
+var lowercaseFilter = valueFn(lowercase);
+
+
+/**
+ * @ngdoc filter
+ * @name uppercase
+ * @kind function
+ * @description
+ * Converts string to uppercase.
+ * @see angular.uppercase
+ */
+var uppercaseFilter = valueFn(uppercase);
+
+/**
+ * @ngdoc filter
+ * @name limitTo
+ * @kind function
+ *
+ * @description
+ * Creates a new array or string containing only a specified number of elements. The elements
+ * are taken from either the beginning or the end of the source array, string or number, as specified by
+ * the value and sign (positive or negative) of `limit`. If a number is used as input, it is
+ * converted to a string.
+ *
+ * @param {Array|string|number} input Source array, string or number to be limited.
+ * @param {string|number} limit The length of the returned array or string. If the `limit` number
+ * is positive, `limit` number of items from the beginning of the source array/string are copied.
+ * If the number is negative, `limit` number of items from the end of the source array/string
+ * are copied. The `limit` will be trimmed if it exceeds `array.length`
+ * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
+ * had less than `limit` elements.
+ *
+ * @example
+ <example module="limitToExample">
+ <file name="index.html">
+ <script>
+ angular.module('limitToExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.numbers = [1,2,3,4,5,6,7,8,9];
+ $scope.letters = "abcdefghi";
+ $scope.longNumber = 2345432342;
+ $scope.numLimit = 3;
+ $scope.letterLimit = 3;
+ $scope.longNumberLimit = 3;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Limit {{numbers}} to: <input type="number" step="1" ng-model="numLimit">
+ <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
+ Limit {{letters}} to: <input type="number" step="1" ng-model="letterLimit">
+ <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
+ Limit {{longNumber}} to: <input type="number" step="1" ng-model="longNumberLimit">
+ <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var numLimitInput = element(by.model('numLimit'));
+ var letterLimitInput = element(by.model('letterLimit'));
+ var longNumberLimitInput = element(by.model('longNumberLimit'));
+ var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
+ var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
+ var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));
+
+ it('should limit the number array to first three items', function() {
+ expect(numLimitInput.getAttribute('value')).toBe('3');
+ expect(letterLimitInput.getAttribute('value')).toBe('3');
+ expect(longNumberLimitInput.getAttribute('value')).toBe('3');
+ expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
+ expect(limitedLetters.getText()).toEqual('Output letters: abc');
+ expect(limitedLongNumber.getText()).toEqual('Output long number: 234');
+ });
+
+ // There is a bug in safari and protractor that doesn't like the minus key
+ // it('should update the output when -3 is entered', function() {
+ // numLimitInput.clear();
+ // numLimitInput.sendKeys('-3');
+ // letterLimitInput.clear();
+ // letterLimitInput.sendKeys('-3');
+ // longNumberLimitInput.clear();
+ // longNumberLimitInput.sendKeys('-3');
+ // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
+ // expect(limitedLetters.getText()).toEqual('Output letters: ghi');
+ // expect(limitedLongNumber.getText()).toEqual('Output long number: 342');
+ // });
+
+ it('should not exceed the maximum size of input array', function() {
+ numLimitInput.clear();
+ numLimitInput.sendKeys('100');
+ letterLimitInput.clear();
+ letterLimitInput.sendKeys('100');
+ longNumberLimitInput.clear();
+ longNumberLimitInput.sendKeys('100');
+ expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
+ expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
+ expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
+ });
+ </file>
+ </example>
+*/
+function limitToFilter() {
+ return function(input, limit) {
+ if (isNumber(input)) input = input.toString();
+ if (!isArray(input) && !isString(input)) return input;
+
+ if (Math.abs(Number(limit)) === Infinity) {
+ limit = Number(limit);
+ } else {
+ limit = int(limit);
+ }
+
+ //NaN check on limit
+ if (limit) {
+ return limit > 0 ? input.slice(0, limit) : input.slice(limit);
+ } else {
+ return isString(input) ? "" : [];
+ }
+ };
+}
+
+/**
+ * @ngdoc filter
+ * @name orderBy
+ * @kind function
+ *
+ * @description
+ * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
+ * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
+ * correctly, make sure they are actually being saved as numbers and not strings.
+ *
+ * @param {Array} array The array to sort.
+ * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
+ * used by the comparator to determine the order of elements.
+ *
+ * Can be one of:
+ *
+ * - `function`: Getter function. The result of this function will be sorted using the
+ * `<`, `===`, `>` operator.
+ * - `string`: An Angular expression. The result of this expression is used to compare elements
+ * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
+ * 3 first characters of a property called `name`). The result of a constant expression
+ * is interpreted as a property name to be used in comparisons (for example `"special name"`
+ * to sort object by the value of their `special name` property). An expression can be
+ * optionally prefixed with `+` or `-` to control ascending or descending sort order
+ * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array
+ * element itself is used to compare where sorting.
+ * - `Array`: An array of function or string predicates. The first predicate in the array
+ * is used for sorting, but when two items are equivalent, the next predicate is used.
+ *
+ * If the predicate is missing or empty then it defaults to `'+'`.
+ *
+ * @param {boolean=} reverse Reverse the order of the array.
+ * @returns {Array} Sorted copy of the source array.
+ *
+ *
+ * @example
+ * The example below demonstrates a simple ngRepeat, where the data is sorted
+ * by age in descending order (predicate is set to `'-age'`).
+ * `reverse` is not set, which means it defaults to `false`.
+ <example module="orderByExample">
+ <file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <table class="friend">
+ <tr>
+ <th>Name</th>
+ <th>Phone Number</th>
+ <th>Age</th>
+ </tr>
+ <tr ng-repeat="friend in friends | orderBy:'-age'">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+ </example>
+ *
+ * The predicate and reverse parameters can be controlled dynamically through scope properties,
+ * as shown in the next example.
+ * @example
+ <example module="orderByExample">
+ <file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ $scope.predicate = '-age';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
+ <hr/>
+ [ <a href="" ng-click="predicate=''">unsorted</a> ]
+ <table class="friend">
+ <tr>
+ <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
+ (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
+ <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
+ <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
+ </tr>
+ <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+ </example>
+ *
+ * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
+ * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
+ * desired parameters.
+ *
+ * Example:
+ *
+ * @example
+ <example module="orderByExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <table class="friend">
+ <tr>
+ <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
+ (<a href="" ng-click="order('-name',false)">^</a>)</th>
+ <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
+ <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
+ </tr>
+ <tr ng-repeat="friend in friends">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
+ var orderBy = $filter('orderBy');
+ $scope.friends = [
+ { name: 'John', phone: '555-1212', age: 10 },
+ { name: 'Mary', phone: '555-9876', age: 19 },
+ { name: 'Mike', phone: '555-4321', age: 21 },
+ { name: 'Adam', phone: '555-5678', age: 35 },
+ { name: 'Julie', phone: '555-8765', age: 29 }
+ ];
+ $scope.order = function(predicate, reverse) {
+ $scope.friends = orderBy($scope.friends, predicate, reverse);
+ };
+ $scope.order('-age',false);
+ }]);
+ </file>
+</example>
+ */
+orderByFilter.$inject = ['$parse'];
+function orderByFilter($parse) {
+ return function(array, sortPredicate, reverseOrder) {
+ if (!(isArrayLike(array))) return array;
+ sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];
+ if (sortPredicate.length === 0) { sortPredicate = ['+']; }
+ sortPredicate = sortPredicate.map(function(predicate) {
+ var descending = false, get = predicate || identity;
+ if (isString(predicate)) {
+ if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
+ descending = predicate.charAt(0) == '-';
+ predicate = predicate.substring(1);
+ }
+ if (predicate === '') {
+ // Effectively no predicate was passed so we compare identity
+ return reverseComparator(compare, descending);
+ }
+ get = $parse(predicate);
+ if (get.constant) {
+ var key = get();
+ return reverseComparator(function(a, b) {
+ return compare(a[key], b[key]);
+ }, descending);
+ }
+ }
+ return reverseComparator(function(a, b) {
+ return compare(get(a),get(b));
+ }, descending);
+ });
+ return slice.call(array).sort(reverseComparator(comparator, reverseOrder));
+
+ function comparator(o1, o2) {
+ for (var i = 0; i < sortPredicate.length; i++) {
+ var comp = sortPredicate[i](o1, o2);
+ if (comp !== 0) return comp;
+ }
+ return 0;
+ }
+ function reverseComparator(comp, descending) {
+ return descending
+ ? function(a, b) {return comp(b,a);}
+ : comp;
+ }
+
+ function isPrimitive(value) {
+ switch (typeof value) {
+ case 'number': /* falls through */
+ case 'boolean': /* falls through */
+ case 'string':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function objectToString(value) {
+ if (value === null) return 'null';
+ if (typeof value.valueOf === 'function') {
+ value = value.valueOf();
+ if (isPrimitive(value)) return value;
+ }
+ if (typeof value.toString === 'function') {
+ value = value.toString();
+ if (isPrimitive(value)) return value;
+ }
+ return '';
+ }
+
+ function compare(v1, v2) {
+ var t1 = typeof v1;
+ var t2 = typeof v2;
+ if (t1 === t2 && t1 === "object") {
+ v1 = objectToString(v1);
+ v2 = objectToString(v2);
+ }
+ if (t1 === t2) {
+ if (t1 === "string") {
+ v1 = v1.toLowerCase();
+ v2 = v2.toLowerCase();
+ }
+ if (v1 === v2) return 0;
+ return v1 < v2 ? -1 : 1;
+ } else {
+ return t1 < t2 ? -1 : 1;
+ }
+ }
+ };
+}
+
+function ngDirective(directive) {
+ if (isFunction(directive)) {
+ directive = {
+ link: directive
+ };
+ }
+ directive.restrict = directive.restrict || 'AC';
+ return valueFn(directive);
+}
+
+/**
+ * @ngdoc directive
+ * @name a
+ * @restrict E
+ *
+ * @description
+ * Modifies the default behavior of the html A tag so that the default action is prevented when
+ * the href attribute is empty.
+ *
+ * This change permits the easy creation of action links with the `ngClick` directive
+ * without changing the location or causing page reloads, e.g.:
+ * `<a href="" ng-click="list.addItem()">Add Item</a>`
+ */
+var htmlAnchorDirective = valueFn({
+ restrict: 'E',
+ compile: function(element, attr) {
+ if (!attr.href && !attr.xlinkHref && !attr.name) {
+ return function(scope, element) {
+ // If the linked element is not an anchor tag anymore, do nothing
+ if (element[0].nodeName.toLowerCase() !== 'a') return;
+
+ // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
+ var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
+ 'xlink:href' : 'href';
+ element.on('click', function(event) {
+ // if we have no href url, then don't navigate anywhere.
+ if (!element.attr(href)) {
+ event.preventDefault();
+ }
+ });
+ };
+ }
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngHref
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in an href attribute will
+ * make the link go to the wrong URL if the user clicks it before
+ * Angular has a chance to replace the `{{hash}}` markup with its
+ * value. Until Angular replaces the markup the link will be broken
+ * and will most likely return a 404 error. The `ngHref` directive
+ * solves this problem.
+ *
+ * The wrong way to write it:
+ * ```html
+ * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
+ * ```
+ *
+ * @element A
+ * @param {template} ngHref any string which can contain `{{}}` markup.
+ *
+ * @example
+ * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
+ * in links and their different behaviors:
+ <example>
+ <file name="index.html">
+ <input ng-model="value" /><br />
+ <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
+ <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
+ <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
+ <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
+ <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
+ <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should execute ng-click but not reload when href without value', function() {
+ element(by.id('link-1')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('1');
+ expect(element(by.id('link-1')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click but not reload when href empty string', function() {
+ element(by.id('link-2')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('2');
+ expect(element(by.id('link-2')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click and change url when ng-href specified', function() {
+ expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);
+
+ element(by.id('link-3')).click();
+
+ // At this point, we navigate away from an Angular page, so we need
+ // to use browser.driver to get the base webdriver.
+
+ browser.wait(function() {
+ return browser.driver.getCurrentUrl().then(function(url) {
+ return url.match(/\/123$/);
+ });
+ }, 5000, 'page should navigate to /123');
+ });
+
+ xit('should execute ng-click but not reload when href empty string and name specified', function() {
+ element(by.id('link-4')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('4');
+ expect(element(by.id('link-4')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click but not reload when no href but name specified', function() {
+ element(by.id('link-5')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('5');
+ expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
+ });
+
+ it('should only change url when only ng-href', function() {
+ element(by.model('value')).clear();
+ element(by.model('value')).sendKeys('6');
+ expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);
+
+ element(by.id('link-6')).click();
+
+ // At this point, we navigate away from an Angular page, so we need
+ // to use browser.driver to get the base webdriver.
+ browser.wait(function() {
+ return browser.driver.getCurrentUrl().then(function(url) {
+ return url.match(/\/6$/);
+ });
+ }, 5000, 'page should navigate to /6');
+ });
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngSrc
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
+ * work right: The browser will fetch from the URL with the literal
+ * text `{{hash}}` until Angular replaces the expression inside
+ * `{{hash}}`. The `ngSrc` directive solves this problem.
+ *
+ * The buggy way to write it:
+ * ```html
+ * <img src="http://www.gravatar.com/avatar/{{hash}}"/>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
+ * ```
+ *
+ * @element IMG
+ * @param {template} ngSrc any string which can contain `{{}}` markup.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngSrcset
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
+ * work right: The browser will fetch from the URL with the literal
+ * text `{{hash}}` until Angular replaces the expression inside
+ * `{{hash}}`. The `ngSrcset` directive solves this problem.
+ *
+ * The buggy way to write it:
+ * ```html
+ * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
+ * ```
+ *
+ * @element IMG
+ * @param {template} ngSrcset any string which can contain `{{}}` markup.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngDisabled
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ *
+ * This directive sets the `disabled` attribute on the element if the
+ * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
+ *
+ * A special directive is necessary because we cannot use interpolation inside the `disabled`
+ * attribute. The following example would make the button enabled on Chrome/Firefox
+ * but not on older IEs:
+ *
+ * ```html
+ * <!-- See below for an example of ng-disabled being used correctly -->
+ * <div ng-init="isDisabled = false">
+ * <button disabled="{{isDisabled}}">Disabled</button>
+ * </div>
+ * ```
+ *
+ * This is because the HTML specification does not require browsers to preserve the values of
+ * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ Click me to toggle: <input type="checkbox" ng-model="checked"><br/>
+ <button ng-model="button" ng-disabled="checked">Button</button>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle button', function() {
+ expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
+ element(by.model('checked')).click();
+ expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
+ * then the `disabled` attribute will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngChecked
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as checked. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngChecked` directive solves this problem for the `checked` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ Check me to check both: <input type="checkbox" ng-model="master"><br/>
+ <input id="checkSlave" type="checkbox" ng-checked="master">
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check both checkBoxes', function() {
+ expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
+ element(by.model('master')).click();
+ expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
+ * then special attribute "checked" will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngReadonly
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as readonly. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngReadonly` directive solves this problem for the `readonly` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/>
+ <input type="text" ng-readonly="checked" value="I'm Angular"/>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle readonly attr', function() {
+ expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
+ element(by.model('checked')).click();
+ expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
+ * then special attribute "readonly" will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngSelected
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as selected. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngSelected` directive solves this problem for the `selected` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ Check me to select: <input type="checkbox" ng-model="selected"><br/>
+ <select>
+ <option>Hello!</option>
+ <option id="greet" ng-selected="selected">Greetings!</option>
+ </select>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should select Greetings!', function() {
+ expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
+ element(by.model('selected')).click();
+ expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element OPTION
+ * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
+ * then special attribute "selected" will be set on the element
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngOpen
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as open. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngOpen` directive solves this problem for the `open` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ Check me check multiple: <input type="checkbox" ng-model="open"><br/>
+ <details id="details" ng-open="open">
+ <summary>Show/Hide me</summary>
+ </details>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle open', function() {
+ expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
+ element(by.model('open')).click();
+ expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element DETAILS
+ * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
+ * then special attribute "open" will be set on the element
+ */
+
+var ngAttributeAliasDirectives = {};
+
+
+// boolean attrs are evaluated
+forEach(BOOLEAN_ATTR, function(propName, attrName) {
+ // binding to multiple is not supported
+ if (propName == "multiple") return;
+
+ var normalized = directiveNormalize('ng-' + attrName);
+ ngAttributeAliasDirectives[normalized] = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ link: function(scope, element, attr) {
+ scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
+ attr.$set(attrName, !!value);
+ });
+ }
+ };
+ };
+});
+
+// aliased input attrs are evaluated
+forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
+ ngAttributeAliasDirectives[ngAttr] = function() {
+ return {
+ priority: 100,
+ link: function(scope, element, attr) {
+ //special case ngPattern when a literal regular expression value
+ //is used as the expression (this way we don't have to watch anything).
+ if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
+ var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
+ if (match) {
+ attr.$set("ngPattern", new RegExp(match[1], match[2]));
+ return;
+ }
+ }
+
+ scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
+ attr.$set(ngAttr, value);
+ });
+ }
+ };
+ };
+});
+
+// ng-src, ng-srcset, ng-href are interpolated
+forEach(['src', 'srcset', 'href'], function(attrName) {
+ var normalized = directiveNormalize('ng-' + attrName);
+ ngAttributeAliasDirectives[normalized] = function() {
+ return {
+ priority: 99, // it needs to run after the attributes are interpolated
+ link: function(scope, element, attr) {
+ var propName = attrName,
+ name = attrName;
+
+ if (attrName === 'href' &&
+ toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
+ name = 'xlinkHref';
+ attr.$attr[name] = 'xlink:href';
+ propName = null;
+ }
+
+ attr.$observe(normalized, function(value) {
+ if (!value) {
+ if (attrName === 'href') {
+ attr.$set(name, null);
+ }
+ return;
+ }
+
+ attr.$set(name, value);
+
+ // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
+ // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
+ // to set the property as well to achieve the desired effect.
+ // we use attr[attrName] value since $set can sanitize the url.
+ if (msie && propName) element.prop(propName, attr[name]);
+ });
+ }
+ };
+ };
+});
+
+/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true
+ */
+var nullFormCtrl = {
+ $addControl: noop,
+ $$renameControl: nullFormRenameControl,
+ $removeControl: noop,
+ $setValidity: noop,
+ $setDirty: noop,
+ $setPristine: noop,
+ $setSubmitted: noop
+},
+SUBMITTED_CLASS = 'ng-submitted';
+
+function nullFormRenameControl(control, name) {
+ control.$name = name;
+}
+
+/**
+ * @ngdoc type
+ * @name form.FormController
+ *
+ * @property {boolean} $pristine True if user has not interacted with the form yet.
+ * @property {boolean} $dirty True if user has already interacted with the form.
+ * @property {boolean} $valid True if all of the containing forms and controls are valid.
+ * @property {boolean} $invalid True if at least one containing control or form is invalid.
+ * @property {boolean} $submitted True if user has submitted the form even if its invalid.
+ *
+ * @property {Object} $error Is an object hash, containing references to controls or
+ * forms with failing validators, where:
+ *
+ * - keys are validation tokens (error names),
+ * - values are arrays of controls or forms that have a failing validator for given error name.
+ *
+ * Built-in validation tokens:
+ *
+ * - `email`
+ * - `max`
+ * - `maxlength`
+ * - `min`
+ * - `minlength`
+ * - `number`
+ * - `pattern`
+ * - `required`
+ * - `url`
+ * - `date`
+ * - `datetimelocal`
+ * - `time`
+ * - `week`
+ * - `month`
+ *
+ * @description
+ * `FormController` keeps track of all its controls and nested forms as well as the state of them,
+ * such as being valid/invalid or dirty/pristine.
+ *
+ * Each {@link ng.directive:form form} directive creates an instance
+ * of `FormController`.
+ *
+ */
+//asks for $scope to fool the BC controller module
+FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];
+function FormController(element, attrs, $scope, $animate, $interpolate) {
+ var form = this,
+ controls = [];
+
+ var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
+
+ // init state
+ form.$error = {};
+ form.$$success = {};
+ form.$pending = undefined;
+ form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);
+ form.$dirty = false;
+ form.$pristine = true;
+ form.$valid = true;
+ form.$invalid = false;
+ form.$submitted = false;
+
+ parentForm.$addControl(form);
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$rollbackViewValue
+ *
+ * @description
+ * Rollback all form controls pending updates to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. This method is typically needed by the reset button of
+ * a form that uses `ng-model-options` to pend updates.
+ */
+ form.$rollbackViewValue = function() {
+ forEach(controls, function(control) {
+ control.$rollbackViewValue();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$commitViewValue
+ *
+ * @description
+ * Commit all form controls pending updates to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`
+ * usually handles calling this in response to input events.
+ */
+ form.$commitViewValue = function() {
+ forEach(controls, function(control) {
+ control.$commitViewValue();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$addControl
+ *
+ * @description
+ * Register a control with the form.
+ *
+ * Input elements using ngModelController do this automatically when they are linked.
+ */
+ form.$addControl = function(control) {
+ // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
+ // and not added to the scope. Now we throw an error.
+ assertNotHasOwnProperty(control.$name, 'input');
+ controls.push(control);
+
+ if (control.$name) {
+ form[control.$name] = control;
+ }
+ };
+
+ // Private API: rename a form control
+ form.$$renameControl = function(control, newName) {
+ var oldName = control.$name;
+
+ if (form[oldName] === control) {
+ delete form[oldName];
+ }
+ form[newName] = control;
+ control.$name = newName;
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$removeControl
+ *
+ * @description
+ * Deregister a control from the form.
+ *
+ * Input elements using ngModelController do this automatically when they are destroyed.
+ */
+ form.$removeControl = function(control) {
+ if (control.$name && form[control.$name] === control) {
+ delete form[control.$name];
+ }
+ forEach(form.$pending, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+ forEach(form.$error, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+ forEach(form.$$success, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+
+ arrayRemove(controls, control);
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setValidity
+ *
+ * @description
+ * Sets the validity of a form control.
+ *
+ * This method will also propagate to parent forms.
+ */
+ addSetValidityMethod({
+ ctrl: this,
+ $element: element,
+ set: function(object, property, controller) {
+ var list = object[property];
+ if (!list) {
+ object[property] = [controller];
+ } else {
+ var index = list.indexOf(controller);
+ if (index === -1) {
+ list.push(controller);
+ }
+ }
+ },
+ unset: function(object, property, controller) {
+ var list = object[property];
+ if (!list) {
+ return;
+ }
+ arrayRemove(list, controller);
+ if (list.length === 0) {
+ delete object[property];
+ }
+ },
+ parentForm: parentForm,
+ $animate: $animate
+ });
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setDirty
+ *
+ * @description
+ * Sets the form to a dirty state.
+ *
+ * This method can be called to add the 'ng-dirty' class and set the form to a dirty
+ * state (ng-dirty class). This method will also propagate to parent forms.
+ */
+ form.$setDirty = function() {
+ $animate.removeClass(element, PRISTINE_CLASS);
+ $animate.addClass(element, DIRTY_CLASS);
+ form.$dirty = true;
+ form.$pristine = false;
+ parentForm.$setDirty();
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setPristine
+ *
+ * @description
+ * Sets the form to its pristine state.
+ *
+ * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
+ * state (ng-pristine class). This method will also propagate to all the controls contained
+ * in this form.
+ *
+ * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
+ * saving or resetting it.
+ */
+ form.$setPristine = function() {
+ $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
+ form.$dirty = false;
+ form.$pristine = true;
+ form.$submitted = false;
+ forEach(controls, function(control) {
+ control.$setPristine();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setUntouched
+ *
+ * @description
+ * Sets the form to its untouched state.
+ *
+ * This method can be called to remove the 'ng-touched' class and set the form controls to their
+ * untouched state (ng-untouched class).
+ *
+ * Setting a form controls back to their untouched state is often useful when setting the form
+ * back to its pristine state.
+ */
+ form.$setUntouched = function() {
+ forEach(controls, function(control) {
+ control.$setUntouched();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setSubmitted
+ *
+ * @description
+ * Sets the form to its submitted state.
+ */
+ form.$setSubmitted = function() {
+ $animate.addClass(element, SUBMITTED_CLASS);
+ form.$submitted = true;
+ parentForm.$setSubmitted();
+ };
+}
+
+/**
+ * @ngdoc directive
+ * @name ngForm
+ * @restrict EAC
+ *
+ * @description
+ * Nestable alias of {@link ng.directive:form `form`} directive. HTML
+ * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
+ * sub-group of controls needs to be determined.
+ *
+ * Note: the purpose of `ngForm` is to group controls,
+ * but not to be a replacement for the `<form>` tag with all of its capabilities
+ * (e.g. posting to the server, ...).
+ *
+ * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
+ * related scope, under this name.
+ *
+ */
+
+ /**
+ * @ngdoc directive
+ * @name form
+ * @restrict E
+ *
+ * @description
+ * Directive that instantiates
+ * {@link form.FormController FormController}.
+ *
+ * If the `name` attribute is specified, the form controller is published onto the current scope under
+ * this name.
+ *
+ * # Alias: {@link ng.directive:ngForm `ngForm`}
+ *
+ * In Angular, forms can be nested. This means that the outer form is valid when all of the child
+ * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
+ * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
+ * `<form>` but can be nested. This allows you to have nested forms, which is very useful when
+ * using Angular validation directives in forms that are dynamically generated using the
+ * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
+ * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
+ * `ngForm` directive and nest these in an outer `form` element.
+ *
+ *
+ * # CSS classes
+ * - `ng-valid` is set if the form is valid.
+ * - `ng-invalid` is set if the form is invalid.
+ * - `ng-pristine` is set if the form is pristine.
+ * - `ng-dirty` is set if the form is dirty.
+ * - `ng-submitted` is set if the form was submitted.
+ *
+ * Keep in mind that ngAnimate can detect each of these classes when added and removed.
+ *
+ *
+ * # Submitting a form and preventing the default action
+ *
+ * Since the role of forms in client-side Angular applications is different than in classical
+ * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
+ * page reload that sends the data to the server. Instead some javascript logic should be triggered
+ * to handle the form submission in an application-specific way.
+ *
+ * For this reason, Angular prevents the default action (form submission to the server) unless the
+ * `<form>` element has an `action` attribute specified.
+ *
+ * You can use one of the following two ways to specify what javascript method should be called when
+ * a form is submitted:
+ *
+ * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
+ * - {@link ng.directive:ngClick ngClick} directive on the first
+ * button or input field of type submit (input[type=submit])
+ *
+ * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
+ * or {@link ng.directive:ngClick ngClick} directives.
+ * This is because of the following form submission rules in the HTML specification:
+ *
+ * - If a form has only one input field then hitting enter in this field triggers form submit
+ * (`ngSubmit`)
+ * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
+ * doesn't trigger submit
+ * - if a form has one or more input fields and one or more buttons or input[type=submit] then
+ * hitting enter in any of the input fields will trigger the click handler on the *first* button or
+ * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
+ *
+ * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is
+ * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
+ * to have access to the updated model.
+ *
+ * ## Animation Hooks
+ *
+ * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
+ * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
+ * other validations that are performed within the form. Animations in ngForm are similar to how
+ * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
+ * as JS animations.
+ *
+ * The following example shows a simple way to utilize CSS transitions to style a form element
+ * that has been rendered as invalid after it has been validated:
+ *
+ * <pre>
+ * //be sure to include ngAnimate as a module to hook into more
+ * //advanced animations
+ * .my-form {
+ * transition:0.5s linear all;
+ * background: white;
+ * }
+ * .my-form.ng-invalid {
+ * background: red;
+ * color:white;
+ * }
+ * </pre>
+ *
+ * @example
+ <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
+ <file name="index.html">
+ <script>
+ angular.module('formExample', [])
+ .controller('FormController', ['$scope', function($scope) {
+ $scope.userType = 'guest';
+ }]);
+ </script>
+ <style>
+ .my-form {
+ -webkit-transition:all linear 0.5s;
+ transition:all linear 0.5s;
+ background: transparent;
+ }
+ .my-form.ng-invalid {
+ background: red;
+ }
+ </style>
+ <form name="myForm" ng-controller="FormController" class="my-form">
+ userType: <input name="input" ng-model="userType" required>
+ <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
+ <code>userType = {{userType}}</code><br>
+ <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
+ <code>myForm.input.$error = {{myForm.input.$error}}</code><br>
+ <code>myForm.$valid = {{myForm.$valid}}</code><br>
+ <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should initialize to model', function() {
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+
+ expect(userType.getText()).toContain('guest');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var userInput = element(by.model('userType'));
+
+ userInput.clear();
+ userInput.sendKeys('');
+
+ expect(userType.getText()).toEqual('userType =');
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ *
+ * @param {string=} name Name of the form. If specified, the form controller will be published into
+ * related scope, under this name.
+ */
+var formDirectiveFactory = function(isNgForm) {
+ return ['$timeout', function($timeout) {
+ var formDirective = {
+ name: 'form',
+ restrict: isNgForm ? 'EAC' : 'E',
+ controller: FormController,
+ compile: function ngFormCompile(formElement, attr) {
+ // Setup initial state of the control
+ formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
+
+ var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
+
+ return {
+ pre: function ngFormPreLink(scope, formElement, attr, controller) {
+ // if `action` attr is not present on the form, prevent the default action (submission)
+ if (!('action' in attr)) {
+ // we can't use jq events because if a form is destroyed during submission the default
+ // action is not prevented. see #1238
+ //
+ // IE 9 is not affected because it doesn't fire a submit event and try to do a full
+ // page reload if the form was destroyed by submission of the form via a click handler
+ // on a button in the form. Looks like an IE9 specific bug.
+ var handleFormSubmission = function(event) {
+ scope.$apply(function() {
+ controller.$commitViewValue();
+ controller.$setSubmitted();
+ });
+
+ event.preventDefault();
+ };
+
+ addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
+
+ // unregister the preventDefault listener so that we don't not leak memory but in a
+ // way that will achieve the prevention of the default action.
+ formElement.on('$destroy', function() {
+ $timeout(function() {
+ removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);
+ }, 0, false);
+ });
+ }
+
+ var parentFormCtrl = controller.$$parentForm;
+
+ if (nameAttr) {
+ setter(scope, null, controller.$name, controller, controller.$name);
+ attr.$observe(nameAttr, function(newValue) {
+ if (controller.$name === newValue) return;
+ setter(scope, null, controller.$name, undefined, controller.$name);
+ parentFormCtrl.$$renameControl(controller, newValue);
+ setter(scope, null, controller.$name, controller, controller.$name);
+ });
+ }
+ formElement.on('$destroy', function() {
+ parentFormCtrl.$removeControl(controller);
+ if (nameAttr) {
+ setter(scope, null, attr[nameAttr], undefined, controller.$name);
+ }
+ extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
+ });
+ }
+ };
+ }
+ };
+
+ return formDirective;
+ }];
+};
+
+var formDirective = formDirectiveFactory();
+var ngFormDirective = formDirectiveFactory(true);
+
+/* global VALID_CLASS: false,
+ INVALID_CLASS: false,
+ PRISTINE_CLASS: false,
+ DIRTY_CLASS: false,
+ UNTOUCHED_CLASS: false,
+ TOUCHED_CLASS: false,
+ ngModelMinErr: false,
+*/
+
+// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
+var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
+var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
+var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
+var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
+var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
+var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
+var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
+var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
+var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
+
+var inputType = {
+
+ /**
+ * @ngdoc input
+ * @name input[text]
+ *
+ * @description
+ * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Adds `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ * This parameter is ignored for input[type=password] controls, which will never trim the
+ * input.
+ *
+ * @example
+ <example name="text-input-directive" module="textInputExample">
+ <file name="index.html">
+ <script>
+ angular.module('textInputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.example = {
+ text: 'guest',
+ word: /^\s*\w*\s*$/
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Single word: <input type="text" name="input" ng-model="example.text"
+ ng-pattern="example.word" required ng-trim="false">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.pattern">
+ Single word only!</span>
+
+ <tt>text = {{example.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('example.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('guest');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if multi word', function() {
+ input.clear();
+ input.sendKeys('hello world');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'text': textInputType,
+
+ /**
+ * @ngdoc input
+ * @name input[date]
+ *
+ * @description
+ * Input with date validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
+ * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
+ * modern browsers do not yet support this input type, it is important to provide cues to users on the
+ * expected input format via a placeholder or label.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO date string (yyyy-MM-dd).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO date string (yyyy-MM-dd).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="date-input-directive" module="dateInputExample">
+ <file name="index.html">
+ <script>
+ angular.module('dateInputExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 9, 22)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a date in 2013:
+ <input type="date" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.date">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM-dd"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (see https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10-22');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'date': createDateInputType('date', DATE_REGEXP,
+ createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
+ 'yyyy-MM-dd'),
+
+ /**
+ * @ngdoc input
+ * @name input[datetime-local]
+ *
+ * @description
+ * Input with datetime validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="datetimelocal-input-directive" module="dateExample">
+ <file name="index.html">
+ <script>
+ angular.module('dateExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2010, 11, 28, 14, 57)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a date between in 2013:
+ <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.datetimelocal">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2010-12-28T14:57:00');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01T23:59:00');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,
+ createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),
+ 'yyyy-MM-ddTHH:mm:ss.sss'),
+
+ /**
+ * @ngdoc input
+ * @name input[time]
+ *
+ * @description
+ * Input with time validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
+ * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO time format (HH:mm:ss).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a
+ * valid ISO time format (HH:mm:ss).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="time-input-directive" module="timeExample">
+ <file name="index.html">
+ <script>
+ angular.module('timeExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(1970, 0, 1, 14, 57, 0)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a between 8am and 5pm:
+ <input type="time" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.time">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "HH:mm:ss"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('14:57:00');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('23:59:00');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'time': createDateInputType('time', TIME_REGEXP,
+ createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),
+ 'HH:mm:ss.sss'),
+
+ /**
+ * @ngdoc input
+ * @name input[week]
+ *
+ * @description
+ * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
+ * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * week format (yyyy-W##), for example: `2013-W02`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO week format (yyyy-W##).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO week format (yyyy-W##).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="week-input-directive" module="weekExample">
+ <file name="index.html">
+ <script>
+ angular.module('weekExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 0, 3)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a date between in 2013:
+ <input id="exampleInput" type="week" name="input" ng-model="example.value"
+ placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.week">
+ Not a valid date!</span>
+ <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-Www"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-W01');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-W01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),
+
+ /**
+ * @ngdoc input
+ * @name input[month]
+ *
+ * @description
+ * Input with month validation and transformation. In browsers that do not yet support
+ * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * month format (yyyy-MM), for example: `2009-01`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ * If the model is not set to the first of the month, the next view to model update will set it
+ * to the first of the month.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be
+ * a valid ISO month format (yyyy-MM).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must
+ * be a valid ISO month format (yyyy-MM).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="month-input-directive" module="monthExample">
+ <file name="index.html">
+ <script>
+ angular.module('monthExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 9, 1)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ Pick a month in 2013:
+ <input id="exampleInput" type="month" name="input" ng-model="example.value"
+ placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.month">
+ Not a valid month!</span>
+ <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'month': createDateInputType('month', MONTH_REGEXP,
+ createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),
+ 'yyyy-MM'),
+
+ /**
+ * @ngdoc input
+ * @name input[number]
+ *
+ * @description
+ * Text input with number validation and transformation. Sets the `number` validation
+ * error if not a valid number.
+ *
+ * <div class="alert alert-warning">
+ * The model must always be of type `number` otherwise Angular will throw an error.
+ * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
+ * error docs for more information and an example of how to convert your model if necessary.
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="number-input-directive" module="numberExample">
+ <file name="index.html">
+ <script>
+ angular.module('numberExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.example = {
+ value: 12
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Number: <input type="number" name="input" ng-model="example.value"
+ min="0" max="99" required>
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.number">
+ Not valid number!</span>
+ <tt>value = {{example.value}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('12');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if over max', function() {
+ input.clear();
+ input.sendKeys('123');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'number': numberInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[url]
+ *
+ * @description
+ * Text input with URL validation. Sets the `url` validation error key if the content is not a
+ * valid URL.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
+ * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
+ * the built-in validators (see the {@link guide/forms Forms guide})
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="url-input-directive" module="urlExample">
+ <file name="index.html">
+ <script>
+ angular.module('urlExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.url = {
+ text: 'http://google.com'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ URL: <input type="url" name="input" ng-model="url.text" required>
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.url">
+ Not valid url!</span>
+ <tt>text = {{url.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('url.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('url.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('http://google.com');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if not url', function() {
+ input.clear();
+ input.sendKeys('box');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'url': urlInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[email]
+ *
+ * @description
+ * Text input with email validation. Sets the `email` validation error key if not a valid email
+ * address.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
+ * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
+ * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="email-input-directive" module="emailExample">
+ <file name="index.html">
+ <script>
+ angular.module('emailExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.email = {
+ text: 'me@example.com'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Email: <input type="email" name="input" ng-model="email.text" required>
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.email">
+ Not valid email!</span>
+ <tt>text = {{email.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('email.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('email.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('me@example.com');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if not email', function() {
+ input.clear();
+ input.sendKeys('xxx');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'email': emailInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[radio]
+ *
+ * @description
+ * HTML radio button.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string} value The value to which the expression should be set when selected.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {string} ngValue Angular expression which sets the value to which the expression should
+ * be set when selected.
+ *
+ * @example
+ <example name="radio-input-directive" module="radioExample">
+ <file name="index.html">
+ <script>
+ angular.module('radioExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.color = {
+ name: 'blue'
+ };
+ $scope.specialValue = {
+ "id": "12345",
+ "value": "green"
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <input type="radio" ng-model="color.name" value="red"> Red <br/>
+ <input type="radio" ng-model="color.name" ng-value="specialValue"> Green <br/>
+ <input type="radio" ng-model="color.name" value="blue"> Blue <br/>
+ <tt>color = {{color.name | json}}</tt><br/>
+ </form>
+ Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should change state', function() {
+ var color = element(by.binding('color.name'));
+
+ expect(color.getText()).toContain('blue');
+
+ element.all(by.model('color.name')).get(0).click();
+
+ expect(color.getText()).toContain('red');
+ });
+ </file>
+ </example>
+ */
+ 'radio': radioInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[checkbox]
+ *
+ * @description
+ * HTML checkbox.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
+ * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="checkbox-input-directive" module="checkboxExample">
+ <file name="index.html">
+ <script>
+ angular.module('checkboxExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.checkboxModel = {
+ value1 : true,
+ value2 : 'YES'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ Value1: <input type="checkbox" ng-model="checkboxModel.value1"> <br/>
+ Value2: <input type="checkbox" ng-model="checkboxModel.value2"
+ ng-true-value="'YES'" ng-false-value="'NO'"> <br/>
+ <tt>value1 = {{checkboxModel.value1}}</tt><br/>
+ <tt>value2 = {{checkboxModel.value2}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should change state', function() {
+ var value1 = element(by.binding('checkboxModel.value1'));
+ var value2 = element(by.binding('checkboxModel.value2'));
+
+ expect(value1.getText()).toContain('true');
+ expect(value2.getText()).toContain('YES');
+
+ element(by.model('checkboxModel.value1')).click();
+ element(by.model('checkboxModel.value2')).click();
+
+ expect(value1.getText()).toContain('false');
+ expect(value2.getText()).toContain('NO');
+ });
+ </file>
+ </example>
+ */
+ 'checkbox': checkboxInputType,
+
+ 'hidden': noop,
+ 'button': noop,
+ 'submit': noop,
+ 'reset': noop,
+ 'file': noop
+};
+
+function stringBasedInputType(ctrl) {
+ ctrl.$formatters.push(function(value) {
+ return ctrl.$isEmpty(value) ? value : value.toString();
+ });
+}
+
+function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+}
+
+function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ var type = lowercase(element[0].type);
+
+ // In composition mode, users are still inputing intermediate text buffer,
+ // hold the listener until composition is done.
+ // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
+ if (!$sniffer.android) {
+ var composing = false;
+
+ element.on('compositionstart', function(data) {
+ composing = true;
+ });
+
+ element.on('compositionend', function() {
+ composing = false;
+ listener();
+ });
+ }
+
+ var listener = function(ev) {
+ if (timeout) {
+ $browser.defer.cancel(timeout);
+ timeout = null;
+ }
+ if (composing) return;
+ var value = element.val(),
+ event = ev && ev.type;
+
+ // By default we will trim the value
+ // If the attribute ng-trim exists we will avoid trimming
+ // If input type is 'password', the value is never trimmed
+ if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
+ value = trim(value);
+ }
+
+ // If a control is suffering from bad input (due to native validators), browsers discard its
+ // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
+ // control's value is the same empty value twice in a row.
+ if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
+ ctrl.$setViewValue(value, event);
+ }
+ };
+
+ // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
+ // input event on backspace, delete or cut
+ if ($sniffer.hasEvent('input')) {
+ element.on('input', listener);
+ } else {
+ var timeout;
+
+ var deferListener = function(ev, input, origValue) {
+ if (!timeout) {
+ timeout = $browser.defer(function() {
+ timeout = null;
+ if (!input || input.value !== origValue) {
+ listener(ev);
+ }
+ });
+ }
+ };
+
+ element.on('keydown', function(event) {
+ var key = event.keyCode;
+
+ // ignore
+ // command modifiers arrows
+ if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
+
+ deferListener(event, this, this.value);
+ });
+
+ // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
+ if ($sniffer.hasEvent('paste')) {
+ element.on('paste cut', deferListener);
+ }
+ }
+
+ // if user paste into input using mouse on older browser
+ // or form autocomplete on newer browser, we need "change" event to catch it
+ element.on('change', listener);
+
+ ctrl.$render = function() {
+ element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
+ };
+}
+
+function weekParser(isoWeek, existingDate) {
+ if (isDate(isoWeek)) {
+ return isoWeek;
+ }
+
+ if (isString(isoWeek)) {
+ WEEK_REGEXP.lastIndex = 0;
+ var parts = WEEK_REGEXP.exec(isoWeek);
+ if (parts) {
+ var year = +parts[1],
+ week = +parts[2],
+ hours = 0,
+ minutes = 0,
+ seconds = 0,
+ milliseconds = 0,
+ firstThurs = getFirstThursdayOfYear(year),
+ addDays = (week - 1) * 7;
+
+ if (existingDate) {
+ hours = existingDate.getHours();
+ minutes = existingDate.getMinutes();
+ seconds = existingDate.getSeconds();
+ milliseconds = existingDate.getMilliseconds();
+ }
+
+ return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);
+ }
+ }
+
+ return NaN;
+}
+
+function createDateParser(regexp, mapping) {
+ return function(iso, date) {
+ var parts, map;
+
+ if (isDate(iso)) {
+ return iso;
+ }
+
+ if (isString(iso)) {
+ // When a date is JSON'ified to wraps itself inside of an extra
+ // set of double quotes. This makes the date parsing code unable
+ // to match the date string and parse it as a date.
+ if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
+ iso = iso.substring(1, iso.length - 1);
+ }
+ if (ISO_DATE_REGEXP.test(iso)) {
+ return new Date(iso);
+ }
+ regexp.lastIndex = 0;
+ parts = regexp.exec(iso);
+
+ if (parts) {
+ parts.shift();
+ if (date) {
+ map = {
+ yyyy: date.getFullYear(),
+ MM: date.getMonth() + 1,
+ dd: date.getDate(),
+ HH: date.getHours(),
+ mm: date.getMinutes(),
+ ss: date.getSeconds(),
+ sss: date.getMilliseconds() / 1000
+ };
+ } else {
+ map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
+ }
+
+ forEach(parts, function(part, index) {
+ if (index < mapping.length) {
+ map[mapping[index]] = +part;
+ }
+ });
+ return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
+ }
+ }
+
+ return NaN;
+ };
+}
+
+function createDateInputType(type, regexp, parseDate, format) {
+ return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
+ badInputChecker(scope, element, attr, ctrl);
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;
+ var previousDate;
+
+ ctrl.$$parserName = type;
+ ctrl.$parsers.push(function(value) {
+ if (ctrl.$isEmpty(value)) return null;
+ if (regexp.test(value)) {
+ // Note: We cannot read ctrl.$modelValue, as there might be a different
+ // parser/formatter in the processing chain so that the model
+ // contains some different data format!
+ var parsedDate = parseDate(value, previousDate);
+ if (timezone === 'UTC') {
+ parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());
+ }
+ return parsedDate;
+ }
+ return undefined;
+ });
+
+ ctrl.$formatters.push(function(value) {
+ if (value && !isDate(value)) {
+ throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
+ }
+ if (isValidDate(value)) {
+ previousDate = value;
+ if (previousDate && timezone === 'UTC') {
+ var timezoneOffset = 60000 * previousDate.getTimezoneOffset();
+ previousDate = new Date(previousDate.getTime() + timezoneOffset);
+ }
+ return $filter('date')(value, format, timezone);
+ } else {
+ previousDate = null;
+ return '';
+ }
+ });
+
+ if (isDefined(attr.min) || attr.ngMin) {
+ var minVal;
+ ctrl.$validators.min = function(value) {
+ return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;
+ };
+ attr.$observe('min', function(val) {
+ minVal = parseObservedDateValue(val);
+ ctrl.$validate();
+ });
+ }
+
+ if (isDefined(attr.max) || attr.ngMax) {
+ var maxVal;
+ ctrl.$validators.max = function(value) {
+ return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
+ };
+ attr.$observe('max', function(val) {
+ maxVal = parseObservedDateValue(val);
+ ctrl.$validate();
+ });
+ }
+
+ function isValidDate(value) {
+ // Invalid Date: getTime() returns NaN
+ return value && !(value.getTime && value.getTime() !== value.getTime());
+ }
+
+ function parseObservedDateValue(val) {
+ return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
+ }
+ };
+}
+
+function badInputChecker(scope, element, attr, ctrl) {
+ var node = element[0];
+ var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);
+ if (nativeValidation) {
+ ctrl.$parsers.push(function(value) {
+ var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
+ // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):
+ // - also sets validity.badInput (should only be validity.typeMismatch).
+ // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
+ // - can ignore this case as we can still read out the erroneous email...
+ return validity.badInput && !validity.typeMismatch ? undefined : value;
+ });
+ }
+}
+
+function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ badInputChecker(scope, element, attr, ctrl);
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+
+ ctrl.$$parserName = 'number';
+ ctrl.$parsers.push(function(value) {
+ if (ctrl.$isEmpty(value)) return null;
+ if (NUMBER_REGEXP.test(value)) return parseFloat(value);
+ return undefined;
+ });
+
+ ctrl.$formatters.push(function(value) {
+ if (!ctrl.$isEmpty(value)) {
+ if (!isNumber(value)) {
+ throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
+ }
+ value = value.toString();
+ }
+ return value;
+ });
+
+ if (isDefined(attr.min) || attr.ngMin) {
+ var minVal;
+ ctrl.$validators.min = function(value) {
+ return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
+ };
+
+ attr.$observe('min', function(val) {
+ if (isDefined(val) && !isNumber(val)) {
+ val = parseFloat(val, 10);
+ }
+ minVal = isNumber(val) && !isNaN(val) ? val : undefined;
+ // TODO(matsko): implement validateLater to reduce number of validations
+ ctrl.$validate();
+ });
+ }
+
+ if (isDefined(attr.max) || attr.ngMax) {
+ var maxVal;
+ ctrl.$validators.max = function(value) {
+ return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
+ };
+
+ attr.$observe('max', function(val) {
+ if (isDefined(val) && !isNumber(val)) {
+ val = parseFloat(val, 10);
+ }
+ maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
+ // TODO(matsko): implement validateLater to reduce number of validations
+ ctrl.$validate();
+ });
+ }
+}
+
+function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ // Note: no badInputChecker here by purpose as `url` is only a validation
+ // in browsers, i.e. we can always read out input.value even if it is not valid!
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+
+ ctrl.$$parserName = 'url';
+ ctrl.$validators.url = function(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+ return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
+ };
+}
+
+function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ // Note: no badInputChecker here by purpose as `url` is only a validation
+ // in browsers, i.e. we can always read out input.value even if it is not valid!
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+
+ ctrl.$$parserName = 'email';
+ ctrl.$validators.email = function(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+ return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
+ };
+}
+
+function radioInputType(scope, element, attr, ctrl) {
+ // make the name unique, if not defined
+ if (isUndefined(attr.name)) {
+ element.attr('name', nextUid());
+ }
+
+ var listener = function(ev) {
+ if (element[0].checked) {
+ ctrl.$setViewValue(attr.value, ev && ev.type);
+ }
+ };
+
+ element.on('click', listener);
+
+ ctrl.$render = function() {
+ var value = attr.value;
+ element[0].checked = (value == ctrl.$viewValue);
+ };
+
+ attr.$observe('value', ctrl.$render);
+}
+
+function parseConstantExpr($parse, context, name, expression, fallback) {
+ var parseFn;
+ if (isDefined(expression)) {
+ parseFn = $parse(expression);
+ if (!parseFn.constant) {
+ throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +
+ '`{1}`.', name, expression);
+ }
+ return parseFn(context);
+ }
+ return fallback;
+}
+
+function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
+ var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
+ var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
+
+ var listener = function(ev) {
+ ctrl.$setViewValue(element[0].checked, ev && ev.type);
+ };
+
+ element.on('click', listener);
+
+ ctrl.$render = function() {
+ element[0].checked = ctrl.$viewValue;
+ };
+
+ // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`
+ // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert
+ // it to a boolean.
+ ctrl.$isEmpty = function(value) {
+ return value === false;
+ };
+
+ ctrl.$formatters.push(function(value) {
+ return equals(value, trueValue);
+ });
+
+ ctrl.$parsers.push(function(value) {
+ return value ? trueValue : falseValue;
+ });
+}
+
+
+/**
+ * @ngdoc directive
+ * @name textarea
+ * @restrict E
+ *
+ * @description
+ * HTML textarea element control with angular data-binding. The data-binding and validation
+ * properties of this element are exactly the same as those of the
+ * {@link ng.directive:input input element}.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
+ * length.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name input
+ * @restrict E
+ *
+ * @description
+ * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
+ * input state control, and validation.
+ * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Not every feature offered is available for all input types.
+ * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {boolean=} ngRequired Sets `required` attribute if set to true
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
+ * length.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ * This parameter is ignored for input[type=password] controls, which will never trim the
+ * input.
+ *
+ * @example
+ <example name="input-directive" module="inputExample">
+ <file name="index.html">
+ <script>
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = {name: 'guest', last: 'visitor'};
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <form name="myForm">
+ User name: <input type="text" name="userName" ng-model="user.name" required>
+ <span class="error" ng-show="myForm.userName.$error.required">
+ Required!</span><br>
+ Last name: <input type="text" name="lastName" ng-model="user.last"
+ ng-minlength="3" ng-maxlength="10">
+ <span class="error" ng-show="myForm.lastName.$error.minlength">
+ Too short!</span>
+ <span class="error" ng-show="myForm.lastName.$error.maxlength">
+ Too long!</span><br>
+ </form>
+ <hr>
+ <tt>user = {{user}}</tt><br/>
+ <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
+ <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
+ <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
+ <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
+ <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
+ <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var user = element(by.exactBinding('user'));
+ var userNameValid = element(by.binding('myForm.userName.$valid'));
+ var lastNameValid = element(by.binding('myForm.lastName.$valid'));
+ var lastNameError = element(by.binding('myForm.lastName.$error'));
+ var formValid = element(by.binding('myForm.$valid'));
+ var userNameInput = element(by.model('user.name'));
+ var userLastInput = element(by.model('user.last'));
+
+ it('should initialize to model', function() {
+ expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
+ expect(userNameValid.getText()).toContain('true');
+ expect(formValid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty when required', function() {
+ userNameInput.clear();
+ userNameInput.sendKeys('');
+
+ expect(user.getText()).toContain('{"last":"visitor"}');
+ expect(userNameValid.getText()).toContain('false');
+ expect(formValid.getText()).toContain('false');
+ });
+
+ it('should be valid if empty when min length is set', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('');
+
+ expect(user.getText()).toContain('{"name":"guest","last":""}');
+ expect(lastNameValid.getText()).toContain('true');
+ expect(formValid.getText()).toContain('true');
+ });
+
+ it('should be invalid if less than required min length', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('xx');
+
+ expect(user.getText()).toContain('{"name":"guest"}');
+ expect(lastNameValid.getText()).toContain('false');
+ expect(lastNameError.getText()).toContain('minlength');
+ expect(formValid.getText()).toContain('false');
+ });
+
+ it('should be invalid if longer than max length', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('some ridiculously long name');
+
+ expect(user.getText()).toContain('{"name":"guest"}');
+ expect(lastNameValid.getText()).toContain('false');
+ expect(lastNameError.getText()).toContain('maxlength');
+ expect(formValid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
+ function($browser, $sniffer, $filter, $parse) {
+ return {
+ restrict: 'E',
+ require: ['?ngModel'],
+ link: {
+ pre: function(scope, element, attr, ctrls) {
+ if (ctrls[0]) {
+ (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
+ $browser, $filter, $parse);
+ }
+ }
+ }
+ };
+}];
+
+
+
+var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
+/**
+ * @ngdoc directive
+ * @name ngValue
+ *
+ * @description
+ * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},
+ * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to
+ * the bound value.
+ *
+ * `ngValue` is useful when dynamically generating lists of radio buttons using
+ * {@link ngRepeat `ngRepeat`}, as shown below.
+ *
+ * Likewise, `ngValue` can be used to generate `<option>` elements for
+ * the {@link select `select`} element. In that case however, only strings are supported
+ * for the `value `attribute, so the resulting `ngModel` will always be a string.
+ * Support for `select` models with non-string values is available via `ngOptions`.
+ *
+ * @element input
+ * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
+ * of the `input` element
+ *
+ * @example
+ <example name="ngValue-directive" module="valueExample">
+ <file name="index.html">
+ <script>
+ angular.module('valueExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.names = ['pizza', 'unicorns', 'robots'];
+ $scope.my = { favorite: 'unicorns' };
+ }]);
+ </script>
+ <form ng-controller="ExampleController">
+ <h2>Which is your favorite?</h2>
+ <label ng-repeat="name in names" for="{{name}}">
+ {{name}}
+ <input type="radio"
+ ng-model="my.favorite"
+ ng-value="name"
+ id="{{name}}"
+ name="favorite">
+ </label>
+ <div>You chose {{my.favorite}}</div>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var favorite = element(by.binding('my.favorite'));
+
+ it('should initialize to model', function() {
+ expect(favorite.getText()).toContain('unicorns');
+ });
+ it('should bind the values to the inputs', function() {
+ element.all(by.model('my.favorite')).get(0).click();
+ expect(favorite.getText()).toContain('pizza');
+ });
+ </file>
+ </example>
+ */
+var ngValueDirective = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ compile: function(tpl, tplAttr) {
+ if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
+ return function ngValueConstantLink(scope, elm, attr) {
+ attr.$set('value', scope.$eval(attr.ngValue));
+ };
+ } else {
+ return function ngValueLink(scope, elm, attr) {
+ scope.$watch(attr.ngValue, function valueWatchAction(value) {
+ attr.$set('value', value);
+ });
+ };
+ }
+ }
+ };
+};
+
+/**
+ * @ngdoc directive
+ * @name ngBind
+ * @restrict AC
+ *
+ * @description
+ * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
+ * with the value of a given expression, and to update the text content when the value of that
+ * expression changes.
+ *
+ * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
+ * `{{ expression }}` which is similar but less verbose.
+ *
+ * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
+ * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
+ * element attribute, it makes the bindings invisible to the user while the page is loading.
+ *
+ * An alternative solution to this problem would be using the
+ * {@link ng.directive:ngCloak ngCloak} directive.
+ *
+ *
+ * @element ANY
+ * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
+ *
+ * @example
+ * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
+ <example module="bindExample">
+ <file name="index.html">
+ <script>
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.name = 'Whirled';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Enter name: <input type="text" ng-model="name"><br>
+ Hello <span ng-bind="name"></span>!
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind', function() {
+ var nameInput = element(by.model('name'));
+
+ expect(element(by.binding('name')).getText()).toBe('Whirled');
+ nameInput.clear();
+ nameInput.sendKeys('world');
+ expect(element(by.binding('name')).getText()).toBe('world');
+ });
+ </file>
+ </example>
+ */
+var ngBindDirective = ['$compile', function($compile) {
+ return {
+ restrict: 'AC',
+ compile: function ngBindCompile(templateElement) {
+ $compile.$$addBindingClass(templateElement);
+ return function ngBindLink(scope, element, attr) {
+ $compile.$$addBindingInfo(element, attr.ngBind);
+ element = element[0];
+ scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
+ element.textContent = value === undefined ? '' : value;
+ });
+ };
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngBindTemplate
+ *
+ * @description
+ * The `ngBindTemplate` directive specifies that the element
+ * text content should be replaced with the interpolation of the template
+ * in the `ngBindTemplate` attribute.
+ * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
+ * expressions. This directive is needed since some HTML elements
+ * (such as TITLE and OPTION) cannot contain SPAN elements.
+ *
+ * @element ANY
+ * @param {string} ngBindTemplate template of form
+ * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
+ *
+ * @example
+ * Try it here: enter text in text box and watch the greeting change.
+ <example module="bindExample">
+ <file name="index.html">
+ <script>
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.salutation = 'Hello';
+ $scope.name = 'World';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Salutation: <input type="text" ng-model="salutation"><br>
+ Name: <input type="text" ng-model="name"><br>
+ <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind', function() {
+ var salutationElem = element(by.binding('salutation'));
+ var salutationInput = element(by.model('salutation'));
+ var nameInput = element(by.model('name'));
+
+ expect(salutationElem.getText()).toBe('Hello World!');
+
+ salutationInput.clear();
+ salutationInput.sendKeys('Greetings');
+ nameInput.clear();
+ nameInput.sendKeys('user');
+
+ expect(salutationElem.getText()).toBe('Greetings user!');
+ });
+ </file>
+ </example>
+ */
+var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {
+ return {
+ compile: function ngBindTemplateCompile(templateElement) {
+ $compile.$$addBindingClass(templateElement);
+ return function ngBindTemplateLink(scope, element, attr) {
+ var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
+ $compile.$$addBindingInfo(element, interpolateFn.expressions);
+ element = element[0];
+ attr.$observe('ngBindTemplate', function(value) {
+ element.textContent = value === undefined ? '' : value;
+ });
+ };
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngBindHtml
+ *
+ * @description
+ * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
+ * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
+ * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
+ * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
+ * in your module's dependencies, you need to include "angular-sanitize.js" in your application.
+ *
+ * You may also bypass sanitization for values you know are safe. To do so, bind to
+ * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example
+ * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.
+ *
+ * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
+ * will have an exception (instead of an exploit.)
+ *
+ * @element ANY
+ * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
+ *
+ * @example
+
+ <example module="bindHtmlExample" deps="angular-sanitize.js">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <p ng-bind-html="myHTML"></p>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('bindHtmlExample', ['ngSanitize'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.myHTML =
+ 'I am an <code>HTML</code>string with ' +
+ '<a href="#">links!</a> and other <em>stuff</em>';
+ }]);
+ </file>
+
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind-html', function() {
+ expect(element(by.binding('myHTML')).getText()).toBe(
+ 'I am an HTMLstring with links! and other stuff');
+ });
+ </file>
+ </example>
+ */
+var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
+ return {
+ restrict: 'A',
+ compile: function ngBindHtmlCompile(tElement, tAttrs) {
+ var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
+ var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
+ return (value || '').toString();
+ });
+ $compile.$$addBindingClass(tElement);
+
+ return function ngBindHtmlLink(scope, element, attr) {
+ $compile.$$addBindingInfo(element, attr.ngBindHtml);
+
+ scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
+ // we re-evaluate the expr because we want a TrustedValueHolderType
+ // for $sce, not a string
+ element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
+ });
+ };
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngChange
+ *
+ * @description
+ * Evaluate the given expression when the user changes the input.
+ * The expression is evaluated immediately, unlike the JavaScript onchange event
+ * which only triggers at the end of a change (usually, when the user leaves the
+ * form element or presses the return key).
+ *
+ * The `ngChange` expression is only evaluated when a change in the input value causes
+ * a new value to be committed to the model.
+ *
+ * It will not be evaluated:
+ * * if the value returned from the `$parsers` transformation pipeline has not changed
+ * * if the input has continued to be invalid since the model will stay `null`
+ * * if the model is changed programmatically and not by a change to the input value
+ *
+ *
+ * Note, this directive requires `ngModel` to be present.
+ *
+ * @element input
+ * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
+ * in input value.
+ *
+ * @example
+ * <example name="ngChange-directive" module="changeExample">
+ * <file name="index.html">
+ * <script>
+ * angular.module('changeExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.counter = 0;
+ * $scope.change = function() {
+ * $scope.counter++;
+ * };
+ * }]);
+ * </script>
+ * <div ng-controller="ExampleController">
+ * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
+ * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
+ * <label for="ng-change-example2">Confirmed</label><br />
+ * <tt>debug = {{confirmed}}</tt><br/>
+ * <tt>counter = {{counter}}</tt><br/>
+ * </div>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * var counter = element(by.binding('counter'));
+ * var debug = element(by.binding('confirmed'));
+ *
+ * it('should evaluate the expression if changing from view', function() {
+ * expect(counter.getText()).toContain('0');
+ *
+ * element(by.id('ng-change-example1')).click();
+ *
+ * expect(counter.getText()).toContain('1');
+ * expect(debug.getText()).toContain('true');
+ * });
+ *
+ * it('should not evaluate the expression if changing from model', function() {
+ * element(by.id('ng-change-example2')).click();
+
+ * expect(counter.getText()).toContain('0');
+ * expect(debug.getText()).toContain('true');
+ * });
+ * </file>
+ * </example>
+ */
+var ngChangeDirective = valueFn({
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, element, attr, ctrl) {
+ ctrl.$viewChangeListeners.push(function() {
+ scope.$eval(attr.ngChange);
+ });
+ }
+});
+
+function classDirective(name, selector) {
+ name = 'ngClass' + name;
+ return ['$animate', function($animate) {
+ return {
+ restrict: 'AC',
+ link: function(scope, element, attr) {
+ var oldVal;
+
+ scope.$watch(attr[name], ngClassWatchAction, true);
+
+ attr.$observe('class', function(value) {
+ ngClassWatchAction(scope.$eval(attr[name]));
+ });
+
+
+ if (name !== 'ngClass') {
+ scope.$watch('$index', function($index, old$index) {
+ // jshint bitwise: false
+ var mod = $index & 1;
+ if (mod !== (old$index & 1)) {
+ var classes = arrayClasses(scope.$eval(attr[name]));
+ mod === selector ?
+ addClasses(classes) :
+ removeClasses(classes);
+ }
+ });
+ }
+
+ function addClasses(classes) {
+ var newClasses = digestClassCounts(classes, 1);
+ attr.$addClass(newClasses);
+ }
+
+ function removeClasses(classes) {
+ var newClasses = digestClassCounts(classes, -1);
+ attr.$removeClass(newClasses);
+ }
+
+ function digestClassCounts(classes, count) {
+ var classCounts = element.data('$classCounts') || {};
+ var classesToUpdate = [];
+ forEach(classes, function(className) {
+ if (count > 0 || classCounts[className]) {
+ classCounts[className] = (classCounts[className] || 0) + count;
+ if (classCounts[className] === +(count > 0)) {
+ classesToUpdate.push(className);
+ }
+ }
+ });
+ element.data('$classCounts', classCounts);
+ return classesToUpdate.join(' ');
+ }
+
+ function updateClasses(oldClasses, newClasses) {
+ var toAdd = arrayDifference(newClasses, oldClasses);
+ var toRemove = arrayDifference(oldClasses, newClasses);
+ toAdd = digestClassCounts(toAdd, 1);
+ toRemove = digestClassCounts(toRemove, -1);
+ if (toAdd && toAdd.length) {
+ $animate.addClass(element, toAdd);
+ }
+ if (toRemove && toRemove.length) {
+ $animate.removeClass(element, toRemove);
+ }
+ }
+
+ function ngClassWatchAction(newVal) {
+ if (selector === true || scope.$index % 2 === selector) {
+ var newClasses = arrayClasses(newVal || []);
+ if (!oldVal) {
+ addClasses(newClasses);
+ } else if (!equals(newVal,oldVal)) {
+ var oldClasses = arrayClasses(oldVal);
+ updateClasses(oldClasses, newClasses);
+ }
+ }
+ oldVal = shallowCopy(newVal);
+ }
+ }
+ };
+
+ function arrayDifference(tokens1, tokens2) {
+ var values = [];
+
+ outer:
+ for (var i = 0; i < tokens1.length; i++) {
+ var token = tokens1[i];
+ for (var j = 0; j < tokens2.length; j++) {
+ if (token == tokens2[j]) continue outer;
+ }
+ values.push(token);
+ }
+ return values;
+ }
+
+ function arrayClasses(classVal) {
+ if (isArray(classVal)) {
+ return classVal;
+ } else if (isString(classVal)) {
+ return classVal.split(' ');
+ } else if (isObject(classVal)) {
+ var classes = [];
+ forEach(classVal, function(v, k) {
+ if (v) {
+ classes = classes.concat(k.split(' '));
+ }
+ });
+ return classes;
+ }
+ return classVal;
+ }
+ }];
+}
+
+/**
+ * @ngdoc directive
+ * @name ngClass
+ * @restrict AC
+ *
+ * @description
+ * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
+ * an expression that represents all classes to be added.
+ *
+ * The directive operates in three different ways, depending on which of three types the expression
+ * evaluates to:
+ *
+ * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
+ * names.
+ *
+ * 2. If the expression evaluates to an array, each element of the array should be a string that is
+ * one or more space-delimited class names.
+ *
+ * 3. If the expression evaluates to an object, then for each key-value pair of the
+ * object with a truthy value the corresponding key is used as a class name.
+ *
+ * The directive won't add duplicate classes if a particular class was already set.
+ *
+ * When the expression changes, the previously added classes are removed and only then the
+ * new classes are added.
+ *
+ * @animations
+ * **add** - happens just before the class is applied to the elements
+ *
+ * **remove** - happens just before the class is removed from the element
+ *
+ * @element ANY
+ * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
+ * of the evaluation can be a string representing space delimited class
+ * names, an array, or a map of class names to boolean values. In the case of a map, the
+ * names of the properties whose values are truthy will be added as css classes to the
+ * element.
+ *
+ * @example Example that demonstrates basic bindings via ngClass directive.
+ <example>
+ <file name="index.html">
+ <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
+ <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br>
+ <input type="checkbox" ng-model="important"> important (apply "bold" class)<br>
+ <input type="checkbox" ng-model="error"> error (apply "red" class)
+ <hr>
+ <p ng-class="style">Using String Syntax</p>
+ <input type="text" ng-model="style" placeholder="Type: bold strike red">
+ <hr>
+ <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
+ <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
+ <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
+ <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
+ </file>
+ <file name="style.css">
+ .strike {
+ text-decoration: line-through;
+ }
+ .bold {
+ font-weight: bold;
+ }
+ .red {
+ color: red;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var ps = element.all(by.css('p'));
+
+ it('should let you toggle the class', function() {
+
+ expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
+ expect(ps.first().getAttribute('class')).not.toMatch(/red/);
+
+ element(by.model('important')).click();
+ expect(ps.first().getAttribute('class')).toMatch(/bold/);
+
+ element(by.model('error')).click();
+ expect(ps.first().getAttribute('class')).toMatch(/red/);
+ });
+
+ it('should let you toggle string example', function() {
+ expect(ps.get(1).getAttribute('class')).toBe('');
+ element(by.model('style')).clear();
+ element(by.model('style')).sendKeys('red');
+ expect(ps.get(1).getAttribute('class')).toBe('red');
+ });
+
+ it('array example should have 3 classes', function() {
+ expect(ps.last().getAttribute('class')).toBe('');
+ element(by.model('style1')).sendKeys('bold');
+ element(by.model('style2')).sendKeys('strike');
+ element(by.model('style3')).sendKeys('red');
+ expect(ps.last().getAttribute('class')).toBe('bold strike red');
+ });
+ </file>
+ </example>
+
+ ## Animations
+
+ The example below demonstrates how to perform animations using ngClass.
+
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
+ <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
+ <br>
+ <span class="base-class" ng-class="myVar">Sample Text</span>
+ </file>
+ <file name="style.css">
+ .base-class {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ }
+
+ .base-class.my-class {
+ color: red;
+ font-size:3em;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class', function() {
+ expect(element(by.css('.base-class')).getAttribute('class')).not.
+ toMatch(/my-class/);
+
+ element(by.id('setbtn')).click();
+
+ expect(element(by.css('.base-class')).getAttribute('class')).
+ toMatch(/my-class/);
+
+ element(by.id('clearbtn')).click();
+
+ expect(element(by.css('.base-class')).getAttribute('class')).not.
+ toMatch(/my-class/);
+ });
+ </file>
+ </example>
+
+
+ ## ngClass and pre-existing CSS3 Transitions/Animations
+ The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
+ Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
+ any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
+ to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and
+ {@link ng.$animate#removeClass $animate.removeClass}.
+ */
+var ngClassDirective = classDirective('', true);
+
+/**
+ * @ngdoc directive
+ * @name ngClassOdd
+ * @restrict AC
+ *
+ * @description
+ * The `ngClassOdd` and `ngClassEven` directives work exactly as
+ * {@link ng.directive:ngClass ngClass}, except they work in
+ * conjunction with `ngRepeat` and take effect only on odd (even) rows.
+ *
+ * This directive can be applied only within the scope of an
+ * {@link ng.directive:ngRepeat ngRepeat}.
+ *
+ * @element ANY
+ * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
+ * of the evaluation can be a string representing space delimited class names or an array.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
+ <li ng-repeat="name in names">
+ <span ng-class-odd="'odd'" ng-class-even="'even'">
+ {{name}}
+ </span>
+ </li>
+ </ol>
+ </file>
+ <file name="style.css">
+ .odd {
+ color: red;
+ }
+ .even {
+ color: blue;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class-odd and ng-class-even', function() {
+ expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
+ toMatch(/odd/);
+ expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
+ toMatch(/even/);
+ });
+ </file>
+ </example>
+ */
+var ngClassOddDirective = classDirective('Odd', 0);
+
+/**
+ * @ngdoc directive
+ * @name ngClassEven
+ * @restrict AC
+ *
+ * @description
+ * The `ngClassOdd` and `ngClassEven` directives work exactly as
+ * {@link ng.directive:ngClass ngClass}, except they work in
+ * conjunction with `ngRepeat` and take effect only on odd (even) rows.
+ *
+ * This directive can be applied only within the scope of an
+ * {@link ng.directive:ngRepeat ngRepeat}.
+ *
+ * @element ANY
+ * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
+ * result of the evaluation can be a string representing space delimited class names or an array.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
+ <li ng-repeat="name in names">
+ <span ng-class-odd="'odd'" ng-class-even="'even'">
+ {{name}} &nbsp; &nbsp; &nbsp;
+ </span>
+ </li>
+ </ol>
+ </file>
+ <file name="style.css">
+ .odd {
+ color: red;
+ }
+ .even {
+ color: blue;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class-odd and ng-class-even', function() {
+ expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
+ toMatch(/odd/);
+ expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
+ toMatch(/even/);
+ });
+ </file>
+ </example>
+ */
+var ngClassEvenDirective = classDirective('Even', 1);
+
+/**
+ * @ngdoc directive
+ * @name ngCloak
+ * @restrict AC
+ *
+ * @description
+ * The `ngCloak` directive is used to prevent the Angular html template from being briefly
+ * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
+ * directive to avoid the undesirable flicker effect caused by the html template display.
+ *
+ * The directive can be applied to the `<body>` element, but the preferred usage is to apply
+ * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
+ * of the browser view.
+ *
+ * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
+ * `angular.min.js`.
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```css
+ * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
+ * display: none !important;
+ * }
+ * ```
+ *
+ * When this css rule is loaded by the browser, all html elements (including their children) that
+ * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
+ * during the compilation of the template it deletes the `ngCloak` element attribute, making
+ * the compiled element visible.
+ *
+ * For the best result, the `angular.js` script must be loaded in the head section of the html
+ * document; alternatively, the css rule above must be included in the external stylesheet of the
+ * application.
+ *
+ * @element ANY
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div id="template1" ng-cloak>{{ 'hello' }}</div>
+ <div id="template2" class="ng-cloak">{{ 'world' }}</div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should remove the template directive and css class', function() {
+ expect($('#template1').getAttribute('ng-cloak')).
+ toBeNull();
+ expect($('#template2').getAttribute('ng-cloak')).
+ toBeNull();
+ });
+ </file>
+ </example>
+ *
+ */
+var ngCloakDirective = ngDirective({
+ compile: function(element, attr) {
+ attr.$set('ngCloak', undefined);
+ element.removeClass('ng-cloak');
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngController
+ *
+ * @description
+ * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
+ * supports the principles behind the Model-View-Controller design pattern.
+ *
+ * MVC components in angular:
+ *
+ * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
+ * are accessed through bindings.
+ * * View — The template (HTML with data bindings) that is rendered into the View.
+ * * Controller — The `ngController` directive specifies a Controller class; the class contains business
+ * logic behind the application to decorate the scope with functions and values
+ *
+ * Note that you can also attach controllers to the DOM by declaring it in a route definition
+ * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
+ * again using `ng-controller` in the template itself. This will cause the controller to be attached
+ * and executed twice.
+ *
+ * @element ANY
+ * @scope
+ * @priority 500
+ * @param {expression} ngController Name of a constructor function registered with the current
+ * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
+ * that on the current scope evaluates to a constructor function.
+ *
+ * The controller instance can be published into a scope property by specifying
+ * `ng-controller="as propertyName"`.
+ *
+ * If the current `$controllerProvider` is configured to use globals (via
+ * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
+ * also be the name of a globally accessible constructor function (not recommended).
+ *
+ * @example
+ * Here is a simple form for editing user contact information. Adding, removing, clearing, and
+ * greeting are methods declared on the controller (see source tab). These methods can
+ * easily be called from the angular markup. Any changes to the data are automatically reflected
+ * in the View without the need for a manual update.
+ *
+ * Two different declaration styles are included below:
+ *
+ * * one binds methods and properties directly onto the controller using `this`:
+ * `ng-controller="SettingsController1 as settings"`
+ * * one injects `$scope` into the controller:
+ * `ng-controller="SettingsController2"`
+ *
+ * The second option is more common in the Angular community, and is generally used in boilerplates
+ * and in this guide. However, there are advantages to binding properties directly to the controller
+ * and avoiding scope.
+ *
+ * * Using `controller as` makes it obvious which controller you are accessing in the template when
+ * multiple controllers apply to an element.
+ * * If you are writing your controllers as classes you have easier access to the properties and
+ * methods, which will appear on the scope, from inside the controller code.
+ * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
+ * inheritance masking primitives.
+ *
+ * This example demonstrates the `controller as` syntax.
+ *
+ * <example name="ngControllerAs" module="controllerAsExample">
+ * <file name="index.html">
+ * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
+ * Name: <input type="text" ng-model="settings.name"/>
+ * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
+ * Contact:
+ * <ul>
+ * <li ng-repeat="contact in settings.contacts">
+ * <select ng-model="contact.type">
+ * <option>phone</option>
+ * <option>email</option>
+ * </select>
+ * <input type="text" ng-model="contact.value"/>
+ * [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
+ * | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
+ * </li>
+ * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
+ * </ul>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('controllerAsExample', [])
+ * .controller('SettingsController1', SettingsController1);
+ *
+ * function SettingsController1() {
+ * this.name = "John Smith";
+ * this.contacts = [
+ * {type: 'phone', value: '408 555 1212'},
+ * {type: 'email', value: 'john.smith@example.org'} ];
+ * }
+ *
+ * SettingsController1.prototype.greet = function() {
+ * alert(this.name);
+ * };
+ *
+ * SettingsController1.prototype.addContact = function() {
+ * this.contacts.push({type: 'email', value: 'yourname@example.org'});
+ * };
+ *
+ * SettingsController1.prototype.removeContact = function(contactToRemove) {
+ * var index = this.contacts.indexOf(contactToRemove);
+ * this.contacts.splice(index, 1);
+ * };
+ *
+ * SettingsController1.prototype.clearContact = function(contact) {
+ * contact.type = 'phone';
+ * contact.value = '';
+ * };
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it('should check controller as', function() {
+ * var container = element(by.id('ctrl-as-exmpl'));
+ * expect(container.element(by.model('settings.name'))
+ * .getAttribute('value')).toBe('John Smith');
+ *
+ * var firstRepeat =
+ * container.element(by.repeater('contact in settings.contacts').row(0));
+ * var secondRepeat =
+ * container.element(by.repeater('contact in settings.contacts').row(1));
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('408 555 1212');
+ *
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('john.smith@example.org');
+ *
+ * firstRepeat.element(by.linkText('clear')).click();
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('');
+ *
+ * container.element(by.linkText('add')).click();
+ *
+ * expect(container.element(by.repeater('contact in settings.contacts').row(2))
+ * .element(by.model('contact.value'))
+ * .getAttribute('value'))
+ * .toBe('yourname@example.org');
+ * });
+ * </file>
+ * </example>
+ *
+ * This example demonstrates the "attach to `$scope`" style of controller.
+ *
+ * <example name="ngController" module="controllerExample">
+ * <file name="index.html">
+ * <div id="ctrl-exmpl" ng-controller="SettingsController2">
+ * Name: <input type="text" ng-model="name"/>
+ * [ <a href="" ng-click="greet()">greet</a> ]<br/>
+ * Contact:
+ * <ul>
+ * <li ng-repeat="contact in contacts">
+ * <select ng-model="contact.type">
+ * <option>phone</option>
+ * <option>email</option>
+ * </select>
+ * <input type="text" ng-model="contact.value"/>
+ * [ <a href="" ng-click="clearContact(contact)">clear</a>
+ * | <a href="" ng-click="removeContact(contact)">X</a> ]
+ * </li>
+ * <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
+ * </ul>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('controllerExample', [])
+ * .controller('SettingsController2', ['$scope', SettingsController2]);
+ *
+ * function SettingsController2($scope) {
+ * $scope.name = "John Smith";
+ * $scope.contacts = [
+ * {type:'phone', value:'408 555 1212'},
+ * {type:'email', value:'john.smith@example.org'} ];
+ *
+ * $scope.greet = function() {
+ * alert($scope.name);
+ * };
+ *
+ * $scope.addContact = function() {
+ * $scope.contacts.push({type:'email', value:'yourname@example.org'});
+ * };
+ *
+ * $scope.removeContact = function(contactToRemove) {
+ * var index = $scope.contacts.indexOf(contactToRemove);
+ * $scope.contacts.splice(index, 1);
+ * };
+ *
+ * $scope.clearContact = function(contact) {
+ * contact.type = 'phone';
+ * contact.value = '';
+ * };
+ * }
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it('should check controller', function() {
+ * var container = element(by.id('ctrl-exmpl'));
+ *
+ * expect(container.element(by.model('name'))
+ * .getAttribute('value')).toBe('John Smith');
+ *
+ * var firstRepeat =
+ * container.element(by.repeater('contact in contacts').row(0));
+ * var secondRepeat =
+ * container.element(by.repeater('contact in contacts').row(1));
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('408 555 1212');
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('john.smith@example.org');
+ *
+ * firstRepeat.element(by.linkText('clear')).click();
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('');
+ *
+ * container.element(by.linkText('add')).click();
+ *
+ * expect(container.element(by.repeater('contact in contacts').row(2))
+ * .element(by.model('contact.value'))
+ * .getAttribute('value'))
+ * .toBe('yourname@example.org');
+ * });
+ * </file>
+ *</example>
+
+ */
+var ngControllerDirective = [function() {
+ return {
+ restrict: 'A',
+ scope: true,
+ controller: '@',
+ priority: 500
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngCsp
+ *
+ * @element html
+ * @description
+ * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
+ *
+ * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
+ *
+ * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
+ * For Angular to be CSP compatible there are only two things that we need to do differently:
+ *
+ * - don't use `Function` constructor to generate optimized value getters
+ * - don't inject custom stylesheet into the document
+ *
+ * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
+ * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
+ * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
+ * be raised.
+ *
+ * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
+ * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
+ * To make those directives work in CSP mode, include the `angular-csp.css` manually.
+ *
+ * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
+ * autodetection however triggers a CSP error to be logged in the console:
+ *
+ * ```
+ * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
+ * script in the following Content Security Policy directive: "default-src 'self'". Note that
+ * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
+ * ```
+ *
+ * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
+ * directive on the root element of the application or on the `angular.js` script tag, whichever
+ * appears first in the html document.
+ *
+ * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
+ *
+ * @example
+ * This example shows how to apply the `ngCsp` directive to the `html` tag.
+ ```html
+ <!doctype html>
+ <html ng-app ng-csp>
+ ...
+ ...
+ </html>
+ ```
+ * @example
+ // Note: the suffix `.csp` in the example name triggers
+ // csp mode in our http server!
+ <example name="example.csp" module="cspExample" ng-csp="true">
+ <file name="index.html">
+ <div ng-controller="MainController as ctrl">
+ <div>
+ <button ng-click="ctrl.inc()" id="inc">Increment</button>
+ <span id="counter">
+ {{ctrl.counter}}
+ </span>
+ </div>
+
+ <div>
+ <button ng-click="ctrl.evil()" id="evil">Evil</button>
+ <span id="evilError">
+ {{ctrl.evilError}}
+ </span>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('cspExample', [])
+ .controller('MainController', function() {
+ this.counter = 0;
+ this.inc = function() {
+ this.counter++;
+ };
+ this.evil = function() {
+ // jshint evil:true
+ try {
+ eval('1+2');
+ } catch (e) {
+ this.evilError = e.message;
+ }
+ };
+ });
+ </file>
+ <file name="protractor.js" type="protractor">
+ var util, webdriver;
+
+ var incBtn = element(by.id('inc'));
+ var counter = element(by.id('counter'));
+ var evilBtn = element(by.id('evil'));
+ var evilError = element(by.id('evilError'));
+
+ function getAndClearSevereErrors() {
+ return browser.manage().logs().get('browser').then(function(browserLog) {
+ return browserLog.filter(function(logEntry) {
+ return logEntry.level.value > webdriver.logging.Level.WARNING.value;
+ });
+ });
+ }
+
+ function clearErrors() {
+ getAndClearSevereErrors();
+ }
+
+ function expectNoErrors() {
+ getAndClearSevereErrors().then(function(filteredLog) {
+ expect(filteredLog.length).toEqual(0);
+ if (filteredLog.length) {
+ console.log('browser console errors: ' + util.inspect(filteredLog));
+ }
+ });
+ }
+
+ function expectError(regex) {
+ getAndClearSevereErrors().then(function(filteredLog) {
+ var found = false;
+ filteredLog.forEach(function(log) {
+ if (log.message.match(regex)) {
+ found = true;
+ }
+ });
+ if (!found) {
+ throw new Error('expected an error that matches ' + regex);
+ }
+ });
+ }
+
+ beforeEach(function() {
+ util = require('util');
+ webdriver = require('protractor/node_modules/selenium-webdriver');
+ });
+
+ // For now, we only test on Chrome,
+ // as Safari does not load the page with Protractor's injected scripts,
+ // and Firefox webdriver always disables content security policy (#6358)
+ if (browser.params.browser !== 'chrome') {
+ return;
+ }
+
+ it('should not report errors when the page is loaded', function() {
+ // clear errors so we are not dependent on previous tests
+ clearErrors();
+ // Need to reload the page as the page is already loaded when
+ // we come here
+ browser.driver.getCurrentUrl().then(function(url) {
+ browser.get(url);
+ });
+ expectNoErrors();
+ });
+
+ it('should evaluate expressions', function() {
+ expect(counter.getText()).toEqual('0');
+ incBtn.click();
+ expect(counter.getText()).toEqual('1');
+ expectNoErrors();
+ });
+
+ it('should throw and report an error when using "eval"', function() {
+ evilBtn.click();
+ expect(evilError.getText()).toMatch(/Content Security Policy/);
+ expectError(/Content Security Policy/);
+ });
+ </file>
+ </example>
+ */
+
+// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
+// bootstrap the system (before $parse is instantiated), for this reason we just have
+// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
+
+/**
+ * @ngdoc directive
+ * @name ngClick
+ *
+ * @description
+ * The ngClick directive allows you to specify custom behavior when
+ * an element is clicked.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
+ * click. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-click="count = count + 1" ng-init="count=0">
+ Increment
+ </button>
+ <span>
+ count: {{count}}
+ </span>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-click', function() {
+ expect(element(by.binding('count')).getText()).toMatch('0');
+ element(by.css('button')).click();
+ expect(element(by.binding('count')).getText()).toMatch('1');
+ });
+ </file>
+ </example>
+ */
+/*
+ * A collection of directives that allows creation of custom event handlers that are defined as
+ * angular expressions and are compiled and executed within the current scope.
+ */
+var ngEventDirectives = {};
+
+// For events that might fire synchronously during DOM manipulation
+// we need to execute their event handlers asynchronously using $evalAsync,
+// so that they are not executed in an inconsistent state.
+var forceAsyncEvents = {
+ 'blur': true,
+ 'focus': true
+};
+forEach(
+ 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
+ function(eventName) {
+ var directiveName = directiveNormalize('ng-' + eventName);
+ ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
+ return {
+ restrict: 'A',
+ compile: function($element, attr) {
+ // We expose the powerful $event object on the scope that provides access to the Window,
+ // etc. that isn't protected by the fast paths in $parse. We explicitly request better
+ // checks at the cost of speed since event handler expressions are not executed as
+ // frequently as regular change detection.
+ var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
+ return function ngEventHandler(scope, element) {
+ element.on(eventName, function(event) {
+ var callback = function() {
+ fn(scope, {$event:event});
+ };
+ if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
+ scope.$evalAsync(callback);
+ } else {
+ scope.$apply(callback);
+ }
+ });
+ };
+ }
+ };
+ }];
+ }
+);
+
+/**
+ * @ngdoc directive
+ * @name ngDblclick
+ *
+ * @description
+ * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
+ * a dblclick. (The Event object is available as `$event`)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-dblclick="count = count + 1" ng-init="count=0">
+ Increment (on double click)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMousedown
+ *
+ * @description
+ * The ngMousedown directive allows you to specify custom behavior on mousedown event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
+ * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mousedown="count = count + 1" ng-init="count=0">
+ Increment (on mouse down)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseup
+ *
+ * @description
+ * Specify custom behavior on mouseup event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
+ * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseup="count = count + 1" ng-init="count=0">
+ Increment (on mouse up)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngMouseover
+ *
+ * @description
+ * Specify custom behavior on mouseover event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
+ * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseover="count = count + 1" ng-init="count=0">
+ Increment (when mouse is over)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseenter
+ *
+ * @description
+ * Specify custom behavior on mouseenter event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
+ * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseenter="count = count + 1" ng-init="count=0">
+ Increment (when mouse enters)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseleave
+ *
+ * @description
+ * Specify custom behavior on mouseleave event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
+ * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseleave="count = count + 1" ng-init="count=0">
+ Increment (when mouse leaves)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMousemove
+ *
+ * @description
+ * Specify custom behavior on mousemove event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
+ * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mousemove="count = count + 1" ng-init="count=0">
+ Increment (when mouse moves)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeydown
+ *
+ * @description
+ * Specify custom behavior on keydown event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
+ * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-keydown="count = count + 1" ng-init="count=0">
+ key down count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeyup
+ *
+ * @description
+ * Specify custom behavior on keyup event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
+ * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <p>Typing in the input box below updates the key count</p>
+ <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
+
+ <p>Typing in the input box below updates the keycode</p>
+ <input ng-keyup="event=$event">
+ <p>event keyCode: {{ event.keyCode }}</p>
+ <p>event altKey: {{ event.altKey }}</p>
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeypress
+ *
+ * @description
+ * Specify custom behavior on keypress event.
+ *
+ * @element ANY
+ * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
+ * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
+ * and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-keypress="count = count + 1" ng-init="count=0">
+ key press count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngSubmit
+ *
+ * @description
+ * Enables binding angular expressions to onsubmit events.
+ *
+ * Additionally it prevents the default action (which for form means sending the request to the
+ * server and reloading the current page), but only if the form does not contain `action`,
+ * `data-action`, or `x-action` attributes.
+ *
+ * <div class="alert alert-warning">
+ * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
+ * `ngSubmit` handlers together. See the
+ * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
+ * for a detailed discussion of when `ngSubmit` may be triggered.
+ * </div>
+ *
+ * @element form
+ * @priority 0
+ * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
+ * ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example module="submitExample">
+ <file name="index.html">
+ <script>
+ angular.module('submitExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [];
+ $scope.text = 'hello';
+ $scope.submit = function() {
+ if ($scope.text) {
+ $scope.list.push(this.text);
+ $scope.text = '';
+ }
+ };
+ }]);
+ </script>
+ <form ng-submit="submit()" ng-controller="ExampleController">
+ Enter text and hit enter:
+ <input type="text" ng-model="text" name="text" />
+ <input type="submit" id="submit" value="Submit" />
+ <pre>list={{list}}</pre>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-submit', function() {
+ expect(element(by.binding('list')).getText()).toBe('list=[]');
+ element(by.css('#submit')).click();
+ expect(element(by.binding('list')).getText()).toContain('hello');
+ expect(element(by.model('text')).getAttribute('value')).toBe('');
+ });
+ it('should ignore empty strings', function() {
+ expect(element(by.binding('list')).getText()).toBe('list=[]');
+ element(by.css('#submit')).click();
+ element(by.css('#submit')).click();
+ expect(element(by.binding('list')).getText()).toContain('hello');
+ });
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngFocus
+ *
+ * @description
+ * Specify custom behavior on focus event.
+ *
+ * Note: As the `focus` event is executed synchronously when calling `input.focus()`
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
+ * during an `$apply` to ensure a consistent state.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
+ * focus. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ * See {@link ng.directive:ngClick ngClick}
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngBlur
+ *
+ * @description
+ * Specify custom behavior on blur event.
+ *
+ * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
+ * an element has lost focus.
+ *
+ * Note: As the `blur` event is executed synchronously also during DOM manipulations
+ * (e.g. removing a focussed input),
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
+ * during an `$apply` to ensure a consistent state.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
+ * blur. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ * See {@link ng.directive:ngClick ngClick}
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngCopy
+ *
+ * @description
+ * Specify custom behavior on copy event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
+ * copy. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
+ copied: {{copied}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngCut
+ *
+ * @description
+ * Specify custom behavior on cut event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
+ * cut. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
+ cut: {{cut}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngPaste
+ *
+ * @description
+ * Specify custom behavior on paste event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
+ * paste. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
+ pasted: {{paste}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngIf
+ * @restrict A
+ *
+ * @description
+ * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
+ * {expression}. If the expression assigned to `ngIf` evaluates to a false
+ * value then the element is removed from the DOM, otherwise a clone of the
+ * element is reinserted into the DOM.
+ *
+ * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
+ * element in the DOM rather than changing its visibility via the `display` css property. A common
+ * case when this difference is significant is when using css selectors that rely on an element's
+ * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
+ *
+ * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
+ * is created when the element is restored. The scope created within `ngIf` inherits from
+ * its parent scope using
+ * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).
+ * An important implication of this is if `ngModel` is used within `ngIf` to bind to
+ * a javascript primitive defined in the parent scope. In this case any modifications made to the
+ * variable within the child scope will override (hide) the value in the parent scope.
+ *
+ * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
+ * is if an element's class attribute is directly modified after it's compiled, using something like
+ * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
+ * the added class will be lost because the original compiled state is used to regenerate the element.
+ *
+ * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
+ * and `leave` effects.
+ *
+ * @animations
+ * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container
+ * leave - happens just before the `ngIf` contents are removed from the DOM
+ *
+ * @element ANY
+ * @scope
+ * @priority 600
+ * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
+ * the element is removed from the DOM tree. If it is truthy a copy of the compiled
+ * element is added to the DOM tree.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
+ Show when checked:
+ <span ng-if="checked" class="animate-if">
+ This is removed when the checkbox is unchecked.
+ </span>
+ </file>
+ <file name="animations.css">
+ .animate-if {
+ background:white;
+ border:1px solid black;
+ padding:10px;
+ }
+
+ .animate-if.ng-enter, .animate-if.ng-leave {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ }
+
+ .animate-if.ng-enter,
+ .animate-if.ng-leave.ng-leave-active {
+ opacity:0;
+ }
+
+ .animate-if.ng-leave,
+ .animate-if.ng-enter.ng-enter-active {
+ opacity:1;
+ }
+ </file>
+ </example>
+ */
+var ngIfDirective = ['$animate', function($animate) {
+ return {
+ multiElement: true,
+ transclude: 'element',
+ priority: 600,
+ terminal: true,
+ restrict: 'A',
+ $$tlb: true,
+ link: function($scope, $element, $attr, ctrl, $transclude) {
+ var block, childScope, previousElements;
+ $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
+
+ if (value) {
+ if (!childScope) {
+ $transclude(function(clone, newScope) {
+ childScope = newScope;
+ clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
+ // Note: We only need the first/last node of the cloned nodes.
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
+ // by a directive with templateUrl when its template arrives.
+ block = {
+ clone: clone
+ };
+ $animate.enter(clone, $element.parent(), $element);
+ });
+ }
+ } else {
+ if (previousElements) {
+ previousElements.remove();
+ previousElements = null;
+ }
+ if (childScope) {
+ childScope.$destroy();
+ childScope = null;
+ }
+ if (block) {
+ previousElements = getBlockNodes(block.clone);
+ $animate.leave(previousElements).then(function() {
+ previousElements = null;
+ });
+ block = null;
+ }
+ }
+ });
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngInclude
+ * @restrict ECA
+ *
+ * @description
+ * Fetches, compiles and includes an external HTML fragment.
+ *
+ * By default, the template URL is restricted to the same domain and protocol as the
+ * application document. This is done by calling {@link $sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
+ * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
+ * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
+ * ng.$sce Strict Contextual Escaping}.
+ *
+ * In addition, the browser's
+ * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
+ * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
+ * policy may further restrict whether the template is successfully loaded.
+ * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
+ * access on some browsers.
+ *
+ * @animations
+ * enter - animation is used to bring new content into the browser.
+ * leave - animation is used to animate existing content away.
+ *
+ * The enter and leave animation occur concurrently.
+ *
+ * @scope
+ * @priority 400
+ *
+ * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
+ * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
+ * @param {string=} onload Expression to evaluate when a new partial is loaded.
+ *
+ * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
+ * $anchorScroll} to scroll the viewport after the content is loaded.
+ *
+ * - If the attribute is not set, disable scrolling.
+ * - If the attribute is set without value, enable scrolling.
+ * - Otherwise enable scrolling only if the expression evaluates to truthy value.
+ *
+ * @example
+ <example module="includeExample" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <select ng-model="template" ng-options="t.name for t in templates">
+ <option value="">(blank)</option>
+ </select>
+ url of the template: <code>{{template.url}}</code>
+ <hr/>
+ <div class="slide-animate-container">
+ <div class="slide-animate" ng-include="template.url"></div>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('includeExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.templates =
+ [ { name: 'template1.html', url: 'template1.html'},
+ { name: 'template2.html', url: 'template2.html'} ];
+ $scope.template = $scope.templates[0];
+ }]);
+ </file>
+ <file name="template1.html">
+ Content of template1.html
+ </file>
+ <file name="template2.html">
+ Content of template2.html
+ </file>
+ <file name="animations.css">
+ .slide-animate-container {
+ position:relative;
+ background:white;
+ border:1px solid black;
+ height:40px;
+ overflow:hidden;
+ }
+
+ .slide-animate {
+ padding:10px;
+ }
+
+ .slide-animate.ng-enter, .slide-animate.ng-leave {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+
+ position:absolute;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ display:block;
+ padding:10px;
+ }
+
+ .slide-animate.ng-enter {
+ top:-50px;
+ }
+ .slide-animate.ng-enter.ng-enter-active {
+ top:0;
+ }
+
+ .slide-animate.ng-leave {
+ top:0;
+ }
+ .slide-animate.ng-leave.ng-leave-active {
+ top:50px;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var templateSelect = element(by.model('template'));
+ var includeElem = element(by.css('[ng-include]'));
+
+ it('should load template1.html', function() {
+ expect(includeElem.getText()).toMatch(/Content of template1.html/);
+ });
+
+ it('should load template2.html', function() {
+ if (browser.params.browser == 'firefox') {
+ // Firefox can't handle using selects
+ // See https://github.com/angular/protractor/issues/480
+ return;
+ }
+ templateSelect.click();
+ templateSelect.all(by.css('option')).get(2).click();
+ expect(includeElem.getText()).toMatch(/Content of template2.html/);
+ });
+
+ it('should change to blank', function() {
+ if (browser.params.browser == 'firefox') {
+ // Firefox can't handle using selects
+ return;
+ }
+ templateSelect.click();
+ templateSelect.all(by.css('option')).get(0).click();
+ expect(includeElem.isPresent()).toBe(false);
+ });
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentRequested
+ * @eventType emit on the scope ngInclude was declared in
+ * @description
+ * Emitted every time the ngInclude content is requested.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentLoaded
+ * @eventType emit on the current ngInclude scope
+ * @description
+ * Emitted every time the ngInclude content is reloaded.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentError
+ * @eventType emit on the scope ngInclude was declared in
+ * @description
+ * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
+ function($templateRequest, $anchorScroll, $animate) {
+ return {
+ restrict: 'ECA',
+ priority: 400,
+ terminal: true,
+ transclude: 'element',
+ controller: angular.noop,
+ compile: function(element, attr) {
+ var srcExp = attr.ngInclude || attr.src,
+ onloadExp = attr.onload || '',
+ autoScrollExp = attr.autoscroll;
+
+ return function(scope, $element, $attr, ctrl, $transclude) {
+ var changeCounter = 0,
+ currentScope,
+ previousElement,
+ currentElement;
+
+ var cleanupLastIncludeContent = function() {
+ if (previousElement) {
+ previousElement.remove();
+ previousElement = null;
+ }
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+ if (currentElement) {
+ $animate.leave(currentElement).then(function() {
+ previousElement = null;
+ });
+ previousElement = currentElement;
+ currentElement = null;
+ }
+ };
+
+ scope.$watch(srcExp, function ngIncludeWatchAction(src) {
+ var afterAnimation = function() {
+ if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
+ $anchorScroll();
+ }
+ };
+ var thisChangeId = ++changeCounter;
+
+ if (src) {
+ //set the 2nd param to true to ignore the template request error so that the inner
+ //contents and scope can be cleaned up.
+ $templateRequest(src, true).then(function(response) {
+ if (thisChangeId !== changeCounter) return;
+ var newScope = scope.$new();
+ ctrl.template = response;
+
+ // Note: This will also link all children of ng-include that were contained in the original
+ // html. If that content contains controllers, ... they could pollute/change the scope.
+ // However, using ng-include on an element with additional content does not make sense...
+ // Note: We can't remove them in the cloneAttchFn of $transclude as that
+ // function is called before linking the content, which would apply child
+ // directives to non existing elements.
+ var clone = $transclude(newScope, function(clone) {
+ cleanupLastIncludeContent();
+ $animate.enter(clone, null, $element).then(afterAnimation);
+ });
+
+ currentScope = newScope;
+ currentElement = clone;
+
+ currentScope.$emit('$includeContentLoaded', src);
+ scope.$eval(onloadExp);
+ }, function() {
+ if (thisChangeId === changeCounter) {
+ cleanupLastIncludeContent();
+ scope.$emit('$includeContentError', src);
+ }
+ });
+ scope.$emit('$includeContentRequested', src);
+ } else {
+ cleanupLastIncludeContent();
+ ctrl.template = null;
+ }
+ });
+ };
+ }
+ };
+}];
+
+// This directive is called during the $transclude call of the first `ngInclude` directive.
+// It will replace and compile the content of the element with the loaded template.
+// We need this directive so that the element content is already filled when
+// the link function of another directive on the same element as ngInclude
+// is called.
+var ngIncludeFillContentDirective = ['$compile',
+ function($compile) {
+ return {
+ restrict: 'ECA',
+ priority: -400,
+ require: 'ngInclude',
+ link: function(scope, $element, $attr, ctrl) {
+ if (/SVG/.test($element[0].toString())) {
+ // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
+ // support innerHTML, so detect this here and try to generate the contents
+ // specially.
+ $element.empty();
+ $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
+ function namespaceAdaptedClone(clone) {
+ $element.append(clone);
+ }, {futureParentElement: $element});
+ return;
+ }
+
+ $element.html(ctrl.template);
+ $compile($element.contents())(scope);
+ }
+ };
+ }];
+
+/**
+ * @ngdoc directive
+ * @name ngInit
+ * @restrict AC
+ *
+ * @description
+ * The `ngInit` directive allows you to evaluate an expression in the
+ * current scope.
+ *
+ * <div class="alert alert-error">
+ * The only appropriate use of `ngInit` is for aliasing special properties of
+ * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
+ * should use {@link guide/controller controllers} rather than `ngInit`
+ * to initialize values on a scope.
+ * </div>
+ * <div class="alert alert-warning">
+ * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
+ * sure you have parenthesis for correct precedence:
+ * <pre class="prettyprint">
+ * `<div ng-init="test1 = (data | orderBy:'name')"></div>`
+ * </pre>
+ * </div>
+ *
+ * @priority 450
+ *
+ * @element ANY
+ * @param {expression} ngInit {@link guide/expression Expression} to eval.
+ *
+ * @example
+ <example module="initExample">
+ <file name="index.html">
+ <script>
+ angular.module('initExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [['a', 'b'], ['c', 'd']];
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
+ <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
+ <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
+ </div>
+ </div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should alias index positions', function() {
+ var elements = element.all(by.css('.example-init'));
+ expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
+ expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
+ expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
+ expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
+ });
+ </file>
+ </example>
+ */
+var ngInitDirective = ngDirective({
+ priority: 450,
+ compile: function() {
+ return {
+ pre: function(scope, element, attrs) {
+ scope.$eval(attrs.ngInit);
+ }
+ };
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngList
+ *
+ * @description
+ * Text input that converts between a delimited string and an array of strings. The default
+ * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom
+ * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`.
+ *
+ * The behaviour of the directive is affected by the use of the `ngTrim` attribute.
+ * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each
+ * list item is respected. This implies that the user of the directive is responsible for
+ * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a
+ * tab or newline character.
+ * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected
+ * when joining the list items back together) and whitespace around each list item is stripped
+ * before it is added to the model.
+ *
+ * ### Example with Validation
+ *
+ * <example name="ngList-directive" module="listExample">
+ * <file name="app.js">
+ * angular.module('listExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.names = ['morpheus', 'neo', 'trinity'];
+ * }]);
+ * </file>
+ * <file name="index.html">
+ * <form name="myForm" ng-controller="ExampleController">
+ * List: <input name="namesInput" ng-model="names" ng-list required>
+ * <span class="error" ng-show="myForm.namesInput.$error.required">
+ * Required!</span>
+ * <br>
+ * <tt>names = {{names}}</tt><br/>
+ * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
+ * <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
+ * <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ * <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ * </form>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * var listInput = element(by.model('names'));
+ * var names = element(by.exactBinding('names'));
+ * var valid = element(by.binding('myForm.namesInput.$valid'));
+ * var error = element(by.css('span.error'));
+ *
+ * it('should initialize to model', function() {
+ * expect(names.getText()).toContain('["morpheus","neo","trinity"]');
+ * expect(valid.getText()).toContain('true');
+ * expect(error.getCssValue('display')).toBe('none');
+ * });
+ *
+ * it('should be invalid if empty', function() {
+ * listInput.clear();
+ * listInput.sendKeys('');
+ *
+ * expect(names.getText()).toContain('');
+ * expect(valid.getText()).toContain('false');
+ * expect(error.getCssValue('display')).not.toBe('none');
+ * });
+ * </file>
+ * </example>
+ *
+ * ### Example - splitting on whitespace
+ * <example name="ngList-directive-newlines">
+ * <file name="index.html">
+ * <textarea ng-model="list" ng-list="&#10;" ng-trim="false"></textarea>
+ * <pre>{{ list | json }}</pre>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it("should split the text by newlines", function() {
+ * var listInput = element(by.model('list'));
+ * var output = element(by.binding('list | json'));
+ * listInput.sendKeys('abc\ndef\nghi');
+ * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]');
+ * });
+ * </file>
+ * </example>
+ *
+ * @element input
+ * @param {string=} ngList optional delimiter that should be used to split the value.
+ */
+var ngListDirective = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ require: 'ngModel',
+ link: function(scope, element, attr, ctrl) {
+ // We want to control whitespace trimming so we use this convoluted approach
+ // to access the ngList attribute, which doesn't pre-trim the attribute
+ var ngList = element.attr(attr.$attr.ngList) || ', ';
+ var trimValues = attr.ngTrim !== 'false';
+ var separator = trimValues ? trim(ngList) : ngList;
+
+ var parse = function(viewValue) {
+ // If the viewValue is invalid (say required but empty) it will be `undefined`
+ if (isUndefined(viewValue)) return;
+
+ var list = [];
+
+ if (viewValue) {
+ forEach(viewValue.split(separator), function(value) {
+ if (value) list.push(trimValues ? trim(value) : value);
+ });
+ }
+
+ return list;
+ };
+
+ ctrl.$parsers.push(parse);
+ ctrl.$formatters.push(function(value) {
+ if (isArray(value)) {
+ return value.join(ngList);
+ }
+
+ return undefined;
+ });
+
+ // Override the standard $isEmpty because an empty array means the input is empty.
+ ctrl.$isEmpty = function(value) {
+ return !value || !value.length;
+ };
+ }
+ };
+};
+
+/* global VALID_CLASS: true,
+ INVALID_CLASS: true,
+ PRISTINE_CLASS: true,
+ DIRTY_CLASS: true,
+ UNTOUCHED_CLASS: true,
+ TOUCHED_CLASS: true,
+*/
+
+var VALID_CLASS = 'ng-valid',
+ INVALID_CLASS = 'ng-invalid',
+ PRISTINE_CLASS = 'ng-pristine',
+ DIRTY_CLASS = 'ng-dirty',
+ UNTOUCHED_CLASS = 'ng-untouched',
+ TOUCHED_CLASS = 'ng-touched',
+ PENDING_CLASS = 'ng-pending';
+
+var ngModelMinErr = minErr('ngModel');
+
+/**
+ * @ngdoc type
+ * @name ngModel.NgModelController
+ *
+ * @property {string} $viewValue Actual string value in the view.
+ * @property {*} $modelValue The value in the model that the control is bound to.
+ * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
+ the control reads value from the DOM. The functions are called in array order, each passing
+ its return value through to the next. The last return value is forwarded to the
+ {@link ngModel.NgModelController#$validators `$validators`} collection.
+
+Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
+`$viewValue`}.
+
+Returning `undefined` from a parser means a parse error occurred. In that case,
+no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
+will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
+is set to `true`. The parse error is stored in `ngModel.$error.parse`.
+
+ *
+ * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
+ the model value changes. The functions are called in reverse array order, each passing the value through to the
+ next. The last return value is used as the actual DOM value.
+ Used to format / convert values for display in the control.
+ * ```js
+ * function formatter(value) {
+ * if (value) {
+ * return value.toUpperCase();
+ * }
+ * }
+ * ngModel.$formatters.push(formatter);
+ * ```
+ *
+ * @property {Object.<string, function>} $validators A collection of validators that are applied
+ * whenever the model value changes. The key value within the object refers to the name of the
+ * validator while the function refers to the validation operation. The validation operation is
+ * provided with the model value as an argument and must return a true or false value depending
+ * on the response of that validation.
+ *
+ * ```js
+ * ngModel.$validators.validCharacters = function(modelValue, viewValue) {
+ * var value = modelValue || viewValue;
+ * return /[0-9]+/.test(value) &&
+ * /[a-z]+/.test(value) &&
+ * /[A-Z]+/.test(value) &&
+ * /\W+/.test(value);
+ * };
+ * ```
+ *
+ * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
+ * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
+ * is expected to return a promise when it is run during the model validation process. Once the promise
+ * is delivered then the validation status will be set to true when fulfilled and false when rejected.
+ * When the asynchronous validators are triggered, each of the validators will run in parallel and the model
+ * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
+ * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
+ * will only run once all synchronous validators have passed.
+ *
+ * Please note that if $http is used then it is important that the server returns a success HTTP response code
+ * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
+ *
+ * ```js
+ * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
+ * var value = modelValue || viewValue;
+ *
+ * // Lookup user by username
+ * return $http.get('/api/users/' + value).
+ * then(function resolved() {
+ * //username exists, this means validation fails
+ * return $q.reject('exists');
+ * }, function rejected() {
+ * //username does not exist, therefore this validation passes
+ * return true;
+ * });
+ * };
+ * ```
+ *
+ * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
+ * view value has changed. It is called with no arguments, and its return value is ignored.
+ * This can be used in place of additional $watches against the model value.
+ *
+ * @property {Object} $error An object hash with all failing validator ids as keys.
+ * @property {Object} $pending An object hash with all pending validator ids as keys.
+ *
+ * @property {boolean} $untouched True if control has not lost focus yet.
+ * @property {boolean} $touched True if control has lost focus.
+ * @property {boolean} $pristine True if user has not interacted with the control yet.
+ * @property {boolean} $dirty True if user has already interacted with the control.
+ * @property {boolean} $valid True if there is no error.
+ * @property {boolean} $invalid True if at least one error on the control.
+ * @property {string} $name The name attribute of the control.
+ *
+ * @description
+ *
+ * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.
+ * The controller contains services for data-binding, validation, CSS updates, and value formatting
+ * and parsing. It purposefully does not contain any logic which deals with DOM rendering or
+ * listening to DOM events.
+ * Such DOM related logic should be provided by other directives which make use of
+ * `NgModelController` for data-binding to control elements.
+ * Angular provides this DOM logic for most {@link input `input`} elements.
+ * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example
+ * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.
+ *
+ * @example
+ * ### Custom Control Example
+ * This example shows how to use `NgModelController` with a custom control to achieve
+ * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
+ * collaborate together to achieve the desired result.
+ *
+ * `contenteditable` is an HTML5 attribute, which tells the browser to let the element
+ * contents be edited in place by the user.
+ *
+ * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
+ * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
+ * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
+ * that content using the `$sce` service.
+ *
+ * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
+ <file name="style.css">
+ [contenteditable] {
+ border: 1px solid black;
+ background-color: white;
+ min-height: 20px;
+ }
+
+ .ng-invalid {
+ border: 1px solid red;
+ }
+
+ </file>
+ <file name="script.js">
+ angular.module('customControl', ['ngSanitize']).
+ directive('contenteditable', ['$sce', function($sce) {
+ return {
+ restrict: 'A', // only activate on element attribute
+ require: '?ngModel', // get a hold of NgModelController
+ link: function(scope, element, attrs, ngModel) {
+ if (!ngModel) return; // do nothing if no ng-model
+
+ // Specify how UI should be updated
+ ngModel.$render = function() {
+ element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
+ };
+
+ // Listen for change events to enable binding
+ element.on('blur keyup change', function() {
+ scope.$evalAsync(read);
+ });
+ read(); // initialize
+
+ // Write data to the model
+ function read() {
+ var html = element.html();
+ // When we clear the content editable the browser leaves a <br> behind
+ // If strip-br attribute is provided then we strip this out
+ if ( attrs.stripBr && html == '<br>' ) {
+ html = '';
+ }
+ ngModel.$setViewValue(html);
+ }
+ }
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <form name="myForm">
+ <div contenteditable
+ name="myWidget" ng-model="userContent"
+ strip-br="true"
+ required>Change me!</div>
+ <span ng-show="myForm.myWidget.$error.required">Required!</span>
+ <hr>
+ <textarea ng-model="userContent"></textarea>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should data-bind and become invalid', function() {
+ if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
+ // SafariDriver can't handle contenteditable
+ // and Firefox driver can't clear contenteditables very well
+ return;
+ }
+ var contentEditable = element(by.css('[contenteditable]'));
+ var content = 'Change me!';
+
+ expect(contentEditable.getText()).toEqual(content);
+
+ contentEditable.clear();
+ contentEditable.sendKeys(protractor.Key.BACK_SPACE);
+ expect(contentEditable.getText()).toEqual('');
+ expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
+ });
+ </file>
+ * </example>
+ *
+ *
+ */
+var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
+ function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
+ this.$viewValue = Number.NaN;
+ this.$modelValue = Number.NaN;
+ this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
+ this.$validators = {};
+ this.$asyncValidators = {};
+ this.$parsers = [];
+ this.$formatters = [];
+ this.$viewChangeListeners = [];
+ this.$untouched = true;
+ this.$touched = false;
+ this.$pristine = true;
+ this.$dirty = false;
+ this.$valid = true;
+ this.$invalid = false;
+ this.$error = {}; // keep invalid keys here
+ this.$$success = {}; // keep valid keys here
+ this.$pending = undefined; // keep pending keys here
+ this.$name = $interpolate($attr.name || '', false)($scope);
+
+
+ var parsedNgModel = $parse($attr.ngModel),
+ parsedNgModelAssign = parsedNgModel.assign,
+ ngModelGet = parsedNgModel,
+ ngModelSet = parsedNgModelAssign,
+ pendingDebounce = null,
+ parserValid,
+ ctrl = this;
+
+ this.$$setOptions = function(options) {
+ ctrl.$options = options;
+ if (options && options.getterSetter) {
+ var invokeModelGetter = $parse($attr.ngModel + '()'),
+ invokeModelSetter = $parse($attr.ngModel + '($$$p)');
+
+ ngModelGet = function($scope) {
+ var modelValue = parsedNgModel($scope);
+ if (isFunction(modelValue)) {
+ modelValue = invokeModelGetter($scope);
+ }
+ return modelValue;
+ };
+ ngModelSet = function($scope, newValue) {
+ if (isFunction(parsedNgModel($scope))) {
+ invokeModelSetter($scope, {$$$p: ctrl.$modelValue});
+ } else {
+ parsedNgModelAssign($scope, ctrl.$modelValue);
+ }
+ };
+ } else if (!parsedNgModel.assign) {
+ throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
+ $attr.ngModel, startingTag($element));
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$render
+ *
+ * @description
+ * Called when the view needs to be updated. It is expected that the user of the ng-model
+ * directive will implement this method.
+ *
+ * The `$render()` method is invoked in the following situations:
+ *
+ * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last
+ * committed value then `$render()` is called to update the input control.
+ * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
+ * the `$viewValue` are different to last time.
+ *
+ * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
+ * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`
+ * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
+ * invoked if you only change a property on the objects.
+ */
+ this.$render = noop;
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$isEmpty
+ *
+ * @description
+ * This is called when we need to determine if the value of an input is empty.
+ *
+ * For instance, the required directive does this to work out if the input has data or not.
+ *
+ * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
+ *
+ * You can override this for input directives whose concept of being empty is different to the
+ * default. The `checkboxInputType` directive does this because in its case a value of `false`
+ * implies empty.
+ *
+ * @param {*} value The value of the input to check for emptiness.
+ * @returns {boolean} True if `value` is "empty".
+ */
+ this.$isEmpty = function(value) {
+ return isUndefined(value) || value === '' || value === null || value !== value;
+ };
+
+ var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
+ currentValidationRunId = 0;
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setValidity
+ *
+ * @description
+ * Change the validity state, and notify the form.
+ *
+ * This method can be called within $parsers/$formatters or a custom validation implementation.
+ * However, in most cases it should be sufficient to use the `ngModel.$validators` and
+ * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
+ *
+ * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
+ * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
+ * (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
+ * The `validationErrorKey` should be in camelCase and will get converted into dash-case
+ * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
+ * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
+ * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
+ * or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
+ * Skipped is used by Angular when validators do not run because of parse errors and
+ * when `$asyncValidators` do not run because any of the `$validators` failed.
+ */
+ addSetValidityMethod({
+ ctrl: this,
+ $element: $element,
+ set: function(object, property) {
+ object[property] = true;
+ },
+ unset: function(object, property) {
+ delete object[property];
+ },
+ parentForm: parentForm,
+ $animate: $animate
+ });
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setPristine
+ *
+ * @description
+ * Sets the control to its pristine state.
+ *
+ * This method can be called to remove the `ng-dirty` class and set the control to its pristine
+ * state (`ng-pristine` class). A model is considered to be pristine when the control
+ * has not been changed from when first compiled.
+ */
+ this.$setPristine = function() {
+ ctrl.$dirty = false;
+ ctrl.$pristine = true;
+ $animate.removeClass($element, DIRTY_CLASS);
+ $animate.addClass($element, PRISTINE_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setDirty
+ *
+ * @description
+ * Sets the control to its dirty state.
+ *
+ * This method can be called to remove the `ng-pristine` class and set the control to its dirty
+ * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed
+ * from when first compiled.
+ */
+ this.$setDirty = function() {
+ ctrl.$dirty = true;
+ ctrl.$pristine = false;
+ $animate.removeClass($element, PRISTINE_CLASS);
+ $animate.addClass($element, DIRTY_CLASS);
+ parentForm.$setDirty();
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setUntouched
+ *
+ * @description
+ * Sets the control to its untouched state.
+ *
+ * This method can be called to remove the `ng-touched` class and set the control to its
+ * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched
+ * by default, however this function can be used to restore that state if the model has
+ * already been touched by the user.
+ */
+ this.$setUntouched = function() {
+ ctrl.$touched = false;
+ ctrl.$untouched = true;
+ $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setTouched
+ *
+ * @description
+ * Sets the control to its touched state.
+ *
+ * This method can be called to remove the `ng-untouched` class and set the control to its
+ * touched state (`ng-touched` class). A model is considered to be touched when the user has
+ * first focused the control element and then shifted focus away from the control (blur event).
+ */
+ this.$setTouched = function() {
+ ctrl.$touched = true;
+ ctrl.$untouched = false;
+ $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$rollbackViewValue
+ *
+ * @description
+ * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,
+ * which may be caused by a pending debounced event or because the input is waiting for a some
+ * future event.
+ *
+ * If you have an input that uses `ng-model-options` to set up debounced events or events such
+ * as blur you can have a situation where there is a period when the `$viewValue`
+ * is out of synch with the ngModel's `$modelValue`.
+ *
+ * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`
+ * programmatically before these debounced/future events have resolved/occurred, because Angular's
+ * dirty checking mechanism is not able to tell whether the model has actually changed or not.
+ *
+ * The `$rollbackViewValue()` method should be called before programmatically changing the model of an
+ * input which may have such events pending. This is important in order to make sure that the
+ * input field will be updated with the new model value and any pending operations are cancelled.
+ *
+ * <example name="ng-model-cancel-update" module="cancel-update-example">
+ * <file name="app.js">
+ * angular.module('cancel-update-example', [])
+ *
+ * .controller('CancelUpdateController', ['$scope', function($scope) {
+ * $scope.resetWithCancel = function(e) {
+ * if (e.keyCode == 27) {
+ * $scope.myForm.myInput1.$rollbackViewValue();
+ * $scope.myValue = '';
+ * }
+ * };
+ * $scope.resetWithoutCancel = function(e) {
+ * if (e.keyCode == 27) {
+ * $scope.myValue = '';
+ * }
+ * };
+ * }]);
+ * </file>
+ * <file name="index.html">
+ * <div ng-controller="CancelUpdateController">
+ * <p>Try typing something in each input. See that the model only updates when you
+ * blur off the input.
+ * </p>
+ * <p>Now see what happens if you start typing then press the Escape key</p>
+ *
+ * <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
+ * <p>With $rollbackViewValue()</p>
+ * <input name="myInput1" ng-model="myValue" ng-keydown="resetWithCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
+ *
+ * <p>Without $rollbackViewValue()</p>
+ * <input name="myInput2" ng-model="myValue" ng-keydown="resetWithoutCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
+ * </form>
+ * </div>
+ * </file>
+ * </example>
+ */
+ this.$rollbackViewValue = function() {
+ $timeout.cancel(pendingDebounce);
+ ctrl.$viewValue = ctrl.$$lastCommittedViewValue;
+ ctrl.$render();
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$validate
+ *
+ * @description
+ * Runs each of the registered validators (first synchronous validators and then
+ * asynchronous validators).
+ * If the validity changes to invalid, the model will be set to `undefined`,
+ * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
+ * If the validity changes to valid, it will set the model to the last available valid
+ * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
+ */
+ this.$validate = function() {
+ // ignore $validate before model is initialized
+ if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ return;
+ }
+
+ var viewValue = ctrl.$$lastCommittedViewValue;
+ // Note: we use the $$rawModelValue as $modelValue might have been
+ // set to undefined during a view -> model update that found validation
+ // errors. We can't parse the view here, since that could change
+ // the model although neither viewValue nor the model on the scope changed
+ var modelValue = ctrl.$$rawModelValue;
+
+ var prevValid = ctrl.$valid;
+ var prevModelValue = ctrl.$modelValue;
+
+ var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+
+ ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
+ // If there was no change in validity, don't update the model
+ // This prevents changing an invalid modelValue to undefined
+ if (!allowInvalid && prevValid !== allValid) {
+ // Note: Don't check ctrl.$valid here, as we could have
+ // external validators (e.g. calculated on the server),
+ // that just call $setValidity and need the model value
+ // to calculate their validity.
+ ctrl.$modelValue = allValid ? modelValue : undefined;
+
+ if (ctrl.$modelValue !== prevModelValue) {
+ ctrl.$$writeModelToScope();
+ }
+ }
+ });
+
+ };
+
+ this.$$runValidators = function(modelValue, viewValue, doneCallback) {
+ currentValidationRunId++;
+ var localValidationRunId = currentValidationRunId;
+
+ // check parser error
+ if (!processParseErrors()) {
+ validationDone(false);
+ return;
+ }
+ if (!processSyncValidators()) {
+ validationDone(false);
+ return;
+ }
+ processAsyncValidators();
+
+ function processParseErrors() {
+ var errorKey = ctrl.$$parserName || 'parse';
+ if (parserValid === undefined) {
+ setValidity(errorKey, null);
+ } else {
+ if (!parserValid) {
+ forEach(ctrl.$validators, function(v, name) {
+ setValidity(name, null);
+ });
+ forEach(ctrl.$asyncValidators, function(v, name) {
+ setValidity(name, null);
+ });
+ }
+ // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
+ setValidity(errorKey, parserValid);
+ return parserValid;
+ }
+ return true;
+ }
+
+ function processSyncValidators() {
+ var syncValidatorsValid = true;
+ forEach(ctrl.$validators, function(validator, name) {
+ var result = validator(modelValue, viewValue);
+ syncValidatorsValid = syncValidatorsValid && result;
+ setValidity(name, result);
+ });
+ if (!syncValidatorsValid) {
+ forEach(ctrl.$asyncValidators, function(v, name) {
+ setValidity(name, null);
+ });
+ return false;
+ }
+ return true;
+ }
+
+ function processAsyncValidators() {
+ var validatorPromises = [];
+ var allValid = true;
+ forEach(ctrl.$asyncValidators, function(validator, name) {
+ var promise = validator(modelValue, viewValue);
+ if (!isPromiseLike(promise)) {
+ throw ngModelMinErr("$asyncValidators",
+ "Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
+ }
+ setValidity(name, undefined);
+ validatorPromises.push(promise.then(function() {
+ setValidity(name, true);
+ }, function(error) {
+ allValid = false;
+ setValidity(name, false);
+ }));
+ });
+ if (!validatorPromises.length) {
+ validationDone(true);
+ } else {
+ $q.all(validatorPromises).then(function() {
+ validationDone(allValid);
+ }, noop);
+ }
+ }
+
+ function setValidity(name, isValid) {
+ if (localValidationRunId === currentValidationRunId) {
+ ctrl.$setValidity(name, isValid);
+ }
+ }
+
+ function validationDone(allValid) {
+ if (localValidationRunId === currentValidationRunId) {
+
+ doneCallback(allValid);
+ }
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$commitViewValue
+ *
+ * @description
+ * Commit a pending update to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
+ * usually handles calling this in response to input events.
+ */
+ this.$commitViewValue = function() {
+ var viewValue = ctrl.$viewValue;
+
+ $timeout.cancel(pendingDebounce);
+
+ // If the view value has not changed then we should just exit, except in the case where there is
+ // a native validator on the element. In this case the validation state may have changed even though
+ // the viewValue has stayed empty.
+ if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
+ return;
+ }
+ ctrl.$$lastCommittedViewValue = viewValue;
+
+ // change to dirty
+ if (ctrl.$pristine) {
+ this.$setDirty();
+ }
+ this.$$parseAndValidate();
+ };
+
+ this.$$parseAndValidate = function() {
+ var viewValue = ctrl.$$lastCommittedViewValue;
+ var modelValue = viewValue;
+ parserValid = isUndefined(modelValue) ? undefined : true;
+
+ if (parserValid) {
+ for (var i = 0; i < ctrl.$parsers.length; i++) {
+ modelValue = ctrl.$parsers[i](modelValue);
+ if (isUndefined(modelValue)) {
+ parserValid = false;
+ break;
+ }
+ }
+ }
+ if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ // ctrl.$modelValue has not been touched yet...
+ ctrl.$modelValue = ngModelGet($scope);
+ }
+ var prevModelValue = ctrl.$modelValue;
+ var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+ ctrl.$$rawModelValue = modelValue;
+
+ if (allowInvalid) {
+ ctrl.$modelValue = modelValue;
+ writeToModelIfNeeded();
+ }
+
+ // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
+ // This can happen if e.g. $setViewValue is called from inside a parser
+ ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
+ if (!allowInvalid) {
+ // Note: Don't check ctrl.$valid here, as we could have
+ // external validators (e.g. calculated on the server),
+ // that just call $setValidity and need the model value
+ // to calculate their validity.
+ ctrl.$modelValue = allValid ? modelValue : undefined;
+ writeToModelIfNeeded();
+ }
+ });
+
+ function writeToModelIfNeeded() {
+ if (ctrl.$modelValue !== prevModelValue) {
+ ctrl.$$writeModelToScope();
+ }
+ }
+ };
+
+ this.$$writeModelToScope = function() {
+ ngModelSet($scope, ctrl.$modelValue);
+ forEach(ctrl.$viewChangeListeners, function(listener) {
+ try {
+ listener();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setViewValue
+ *
+ * @description
+ * Update the view value.
+ *
+ * This method should be called when an input directive want to change the view value; typically,
+ * this is done from within a DOM event handler.
+ *
+ * For example {@link ng.directive:input input} calls it when the value of the input changes and
+ * {@link ng.directive:select select} calls it when an option is selected.
+ *
+ * If the new `value` is an object (rather than a string or a number), we should make a copy of the
+ * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
+ * watch of objects, it only looks for a change of identity. If you only change the property of
+ * the object then ngModel will not realise that the object has changed and will not invoke the
+ * `$parsers` and `$validators` pipelines.
+ *
+ * For this reason, you should not change properties of the copy once it has been passed to
+ * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
+ *
+ * When this method is called, the new `value` will be staged for committing through the `$parsers`
+ * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
+ * value sent directly for processing, finally to be applied to `$modelValue` and then the
+ * **expression** specified in the `ng-model` attribute.
+ *
+ * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
+ *
+ * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
+ * and the `default` trigger is not listed, all those actions will remain pending until one of the
+ * `updateOn` events is triggered on the DOM element.
+ * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
+ * directive is used with a custom debounce for this particular event.
+ *
+ * Note that calling this function does not trigger a `$digest`.
+ *
+ * @param {string} value Value from the view.
+ * @param {string} trigger Event that triggered the update.
+ */
+ this.$setViewValue = function(value, trigger) {
+ ctrl.$viewValue = value;
+ if (!ctrl.$options || ctrl.$options.updateOnDefault) {
+ ctrl.$$debounceViewValueCommit(trigger);
+ }
+ };
+
+ this.$$debounceViewValueCommit = function(trigger) {
+ var debounceDelay = 0,
+ options = ctrl.$options,
+ debounce;
+
+ if (options && isDefined(options.debounce)) {
+ debounce = options.debounce;
+ if (isNumber(debounce)) {
+ debounceDelay = debounce;
+ } else if (isNumber(debounce[trigger])) {
+ debounceDelay = debounce[trigger];
+ } else if (isNumber(debounce['default'])) {
+ debounceDelay = debounce['default'];
+ }
+ }
+
+ $timeout.cancel(pendingDebounce);
+ if (debounceDelay) {
+ pendingDebounce = $timeout(function() {
+ ctrl.$commitViewValue();
+ }, debounceDelay);
+ } else if ($rootScope.$$phase) {
+ ctrl.$commitViewValue();
+ } else {
+ $scope.$apply(function() {
+ ctrl.$commitViewValue();
+ });
+ }
+ };
+
+ // model -> value
+ // Note: we cannot use a normal scope.$watch as we want to detect the following:
+ // 1. scope value is 'a'
+ // 2. user enters 'b'
+ // 3. ng-change kicks in and reverts scope value to 'a'
+ // -> scope value did not change since the last digest as
+ // ng-change executes in apply phase
+ // 4. view should be changed back to 'a'
+ $scope.$watch(function ngModelWatch() {
+ var modelValue = ngModelGet($scope);
+
+ // if scope model value and ngModel value are out of sync
+ // TODO(perf): why not move this to the action fn?
+ if (modelValue !== ctrl.$modelValue &&
+ // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
+ (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
+ ) {
+ ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
+ parserValid = undefined;
+
+ var formatters = ctrl.$formatters,
+ idx = formatters.length;
+
+ var viewValue = modelValue;
+ while (idx--) {
+ viewValue = formatters[idx](viewValue);
+ }
+ if (ctrl.$viewValue !== viewValue) {
+ ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
+ ctrl.$render();
+
+ ctrl.$$runValidators(modelValue, viewValue, noop);
+ }
+ }
+
+ return modelValue;
+ });
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngModel
+ *
+ * @element input
+ * @priority 1
+ *
+ * @description
+ * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
+ * property on the scope using {@link ngModel.NgModelController NgModelController},
+ * which is created and exposed by this directive.
+ *
+ * `ngModel` is responsible for:
+ *
+ * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
+ * require.
+ * - Providing validation behavior (i.e. required, number, email, url).
+ * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
+ * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.
+ * - Registering the control with its parent {@link ng.directive:form form}.
+ *
+ * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
+ * current scope. If the property doesn't already exist on this scope, it will be created
+ * implicitly and added to the scope.
+ *
+ * For best practices on using `ngModel`, see:
+ *
+ * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
+ *
+ * For basic examples, how to use `ngModel`, see:
+ *
+ * - {@link ng.directive:input input}
+ * - {@link input[text] text}
+ * - {@link input[checkbox] checkbox}
+ * - {@link input[radio] radio}
+ * - {@link input[number] number}
+ * - {@link input[email] email}
+ * - {@link input[url] url}
+ * - {@link input[date] date}
+ * - {@link input[datetime-local] datetime-local}
+ * - {@link input[time] time}
+ * - {@link input[month] month}
+ * - {@link input[week] week}
+ * - {@link ng.directive:select select}
+ * - {@link ng.directive:textarea textarea}
+ *
+ * # CSS classes
+ * The following CSS classes are added and removed on the associated input/select/textarea element
+ * depending on the validity of the model.
+ *
+ * - `ng-valid`: the model is valid
+ * - `ng-invalid`: the model is invalid
+ * - `ng-valid-[key]`: for each valid key added by `$setValidity`
+ * - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
+ * - `ng-pristine`: the control hasn't been interacted with yet
+ * - `ng-dirty`: the control has been interacted with
+ * - `ng-touched`: the control has been blurred
+ * - `ng-untouched`: the control hasn't been blurred
+ * - `ng-pending`: any `$asyncValidators` are unfulfilled
+ *
+ * Keep in mind that ngAnimate can detect each of these classes when added and removed.
+ *
+ * ## Animation Hooks
+ *
+ * Animations within models are triggered when any of the associated CSS classes are added and removed
+ * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
+ * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
+ * The animations that are triggered within ngModel are similar to how they work in ngClass and
+ * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
+ *
+ * The following example shows a simple way to utilize CSS transitions to style an input element
+ * that has been rendered as invalid after it has been validated:
+ *
+ * <pre>
+ * //be sure to include ngAnimate as a module to hook into more
+ * //advanced animations
+ * .my-input {
+ * transition:0.5s linear all;
+ * background: white;
+ * }
+ * .my-input.ng-invalid {
+ * background: red;
+ * color:white;
+ * }
+ * </pre>
+ *
+ * @example
+ * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
+ <file name="index.html">
+ <script>
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = '1';
+ }]);
+ </script>
+ <style>
+ .my-input {
+ -webkit-transition:all linear 0.5s;
+ transition:all linear 0.5s;
+ background: transparent;
+ }
+ .my-input.ng-invalid {
+ color:white;
+ background: red;
+ }
+ </style>
+ Update input to see transitions when valid/invalid.
+ Integer is a valid value.
+ <form name="testForm" ng-controller="ExampleController">
+ <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
+ </form>
+ </file>
+ * </example>
+ *
+ * ## Binding to a getter/setter
+ *
+ * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
+ * function that returns a representation of the model when called with zero arguments, and sets
+ * the internal state of a model when called with an argument. It's sometimes useful to use this
+ * for models that have an internal representation that's different than what the model exposes
+ * to the view.
+ *
+ * <div class="alert alert-success">
+ * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
+ * frequently than other parts of your code.
+ * </div>
+ *
+ * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
+ * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
+ * a `<form>`, which will enable this behavior for all `<input>`s within it. See
+ * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
+ *
+ * The following example shows how to use `ngModel` with a getter/setter:
+ *
+ * @example
+ * <example name="ngModel-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function(newName) {
+ // Note that newName can be undefined for two reasons:
+ // 1. Because it is called as a getter and thus called with no arguments
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
+ // input is invalid
+ return arguments.length ? (_name = newName) : _name;
+ }
+ };
+ }]);
+ </file>
+ * </example>
+ */
+var ngModelDirective = ['$rootScope', function($rootScope) {
+ return {
+ restrict: 'A',
+ require: ['ngModel', '^?form', '^?ngModelOptions'],
+ controller: NgModelController,
+ // Prelink needs to run before any input directive
+ // so that we can set the NgModelOptions in NgModelController
+ // before anyone else uses it.
+ priority: 1,
+ compile: function ngModelCompile(element) {
+ // Setup initial state of the control
+ element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);
+
+ return {
+ pre: function ngModelPreLink(scope, element, attr, ctrls) {
+ var modelCtrl = ctrls[0],
+ formCtrl = ctrls[1] || nullFormCtrl;
+
+ modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
+
+ // notify others, especially parent forms
+ formCtrl.$addControl(modelCtrl);
+
+ attr.$observe('name', function(newValue) {
+ if (modelCtrl.$name !== newValue) {
+ formCtrl.$$renameControl(modelCtrl, newValue);
+ }
+ });
+
+ scope.$on('$destroy', function() {
+ formCtrl.$removeControl(modelCtrl);
+ });
+ },
+ post: function ngModelPostLink(scope, element, attr, ctrls) {
+ var modelCtrl = ctrls[0];
+ if (modelCtrl.$options && modelCtrl.$options.updateOn) {
+ element.on(modelCtrl.$options.updateOn, function(ev) {
+ modelCtrl.$$debounceViewValueCommit(ev && ev.type);
+ });
+ }
+
+ element.on('blur', function(ev) {
+ if (modelCtrl.$touched) return;
+
+ if ($rootScope.$$phase) {
+ scope.$evalAsync(modelCtrl.$setTouched);
+ } else {
+ scope.$apply(modelCtrl.$setTouched);
+ }
+ });
+ }
+ };
+ }
+ };
+}];
+
+var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
+
+/**
+ * @ngdoc directive
+ * @name ngModelOptions
+ *
+ * @description
+ * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of
+ * events that will trigger a model update and/or a debouncing delay so that the actual update only
+ * takes place when a timer expires; this timer will be reset after another change takes place.
+ *
+ * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might
+ * be different than the value in the actual model. This means that if you update the model you
+ * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in
+ * order to make sure it is synchronized with the model and that any debounced action is canceled.
+ *
+ * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}
+ * method is by making sure the input is placed inside a form that has a `name` attribute. This is
+ * important because `form` controllers are published to the related scope under the name in their
+ * `name` attribute.
+ *
+ * Any pending changes will take place immediately when an enclosing form is submitted via the
+ * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
+ * to have access to the updated model.
+ *
+ * `ngModelOptions` has an effect on the element it's declared on and its descendants.
+ *
+ * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
+ * - `updateOn`: string specifying which event should the input be bound to. You can set several
+ * events using an space delimited list. There is a special event called `default` that
+ * matches the default events belonging of the control.
+ * - `debounce`: integer value which contains the debounce model update value in milliseconds. A
+ * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
+ * custom value for each event. For example:
+ * `ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"`
+ * - `allowInvalid`: boolean value which indicates that the model can be set with values that did
+ * not validate correctly instead of the default behavior of setting the model to undefined.
+ * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
+ `ngModel` as getters/setters.
+ * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for
+ * `<input type="date">`, `<input type="time">`, ... . Right now, the only supported value is `'UTC'`,
+ * otherwise the default timezone of the browser will be used.
+ *
+ * @example
+
+ The following example shows how to override immediate updates. Changes on the inputs within the
+ form will update the model only when the control loses focus (blur event). If `escape` key is
+ pressed while the input field is focused, the value is reset to the value in the current model.
+
+ <example name="ngModelOptions-directive-blur" module="optionsExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ updateOn: 'blur' }"
+ ng-keyup="cancel($event)" /><br />
+
+ Other data:
+ <input type="text" ng-model="user.data" /><br />
+ </form>
+ <pre>user.name = <span ng-bind="user.name"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'say', data: '' };
+
+ $scope.cancel = function(e) {
+ if (e.keyCode == 27) {
+ $scope.userForm.userName.$rollbackViewValue();
+ }
+ };
+ }]);
+ </file>
+ <file name="protractor.js" type="protractor">
+ var model = element(by.binding('user.name'));
+ var input = element(by.model('user.name'));
+ var other = element(by.model('user.data'));
+
+ it('should allow custom events', function() {
+ input.sendKeys(' hello');
+ input.click();
+ expect(model.getText()).toEqual('say');
+ other.click();
+ expect(model.getText()).toEqual('say hello');
+ });
+
+ it('should $rollbackViewValue when model changes', function() {
+ input.sendKeys(' hello');
+ expect(input.getAttribute('value')).toEqual('say hello');
+ input.sendKeys(protractor.Key.ESCAPE);
+ expect(input.getAttribute('value')).toEqual('say');
+ other.click();
+ expect(model.getText()).toEqual('say');
+ });
+ </file>
+ </example>
+
+ This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
+ If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
+
+ <example name="ngModelOptions-directive-debounce" module="optionsExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ debounce: 1000 }" />
+ <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button><br />
+ </form>
+ <pre>user.name = <span ng-bind="user.name"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'say' };
+ }]);
+ </file>
+ </example>
+
+ This one shows how to bind to getter/setters:
+
+ <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function(newName) {
+ // Note that newName can be undefined for two reasons:
+ // 1. Because it is called as a getter and thus called with no arguments
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
+ // input is invalid
+ return arguments.length ? (_name = newName) : _name;
+ }
+ };
+ }]);
+ </file>
+ </example>
+ */
+var ngModelOptionsDirective = function() {
+ return {
+ restrict: 'A',
+ controller: ['$scope', '$attrs', function($scope, $attrs) {
+ var that = this;
+ this.$options = $scope.$eval($attrs.ngModelOptions);
+ // Allow adding/overriding bound events
+ if (this.$options.updateOn !== undefined) {
+ this.$options.updateOnDefault = false;
+ // extract "default" pseudo-event from list of events that can trigger a model update
+ this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
+ that.$options.updateOnDefault = true;
+ return ' ';
+ }));
+ } else {
+ this.$options.updateOnDefault = true;
+ }
+ }]
+ };
+};
+
+
+
+// helper methods
+function addSetValidityMethod(context) {
+ var ctrl = context.ctrl,
+ $element = context.$element,
+ classCache = {},
+ set = context.set,
+ unset = context.unset,
+ parentForm = context.parentForm,
+ $animate = context.$animate;
+
+ classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
+
+ ctrl.$setValidity = setValidity;
+
+ function setValidity(validationErrorKey, state, controller) {
+ if (state === undefined) {
+ createAndSet('$pending', validationErrorKey, controller);
+ } else {
+ unsetAndCleanup('$pending', validationErrorKey, controller);
+ }
+ if (!isBoolean(state)) {
+ unset(ctrl.$error, validationErrorKey, controller);
+ unset(ctrl.$$success, validationErrorKey, controller);
+ } else {
+ if (state) {
+ unset(ctrl.$error, validationErrorKey, controller);
+ set(ctrl.$$success, validationErrorKey, controller);
+ } else {
+ set(ctrl.$error, validationErrorKey, controller);
+ unset(ctrl.$$success, validationErrorKey, controller);
+ }
+ }
+ if (ctrl.$pending) {
+ cachedToggleClass(PENDING_CLASS, true);
+ ctrl.$valid = ctrl.$invalid = undefined;
+ toggleValidationCss('', null);
+ } else {
+ cachedToggleClass(PENDING_CLASS, false);
+ ctrl.$valid = isObjectEmpty(ctrl.$error);
+ ctrl.$invalid = !ctrl.$valid;
+ toggleValidationCss('', ctrl.$valid);
+ }
+
+ // re-read the state as the set/unset methods could have
+ // combined state in ctrl.$error[validationError] (used for forms),
+ // where setting/unsetting only increments/decrements the value,
+ // and does not replace it.
+ var combinedState;
+ if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {
+ combinedState = undefined;
+ } else if (ctrl.$error[validationErrorKey]) {
+ combinedState = false;
+ } else if (ctrl.$$success[validationErrorKey]) {
+ combinedState = true;
+ } else {
+ combinedState = null;
+ }
+
+ toggleValidationCss(validationErrorKey, combinedState);
+ parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
+ }
+
+ function createAndSet(name, value, controller) {
+ if (!ctrl[name]) {
+ ctrl[name] = {};
+ }
+ set(ctrl[name], value, controller);
+ }
+
+ function unsetAndCleanup(name, value, controller) {
+ if (ctrl[name]) {
+ unset(ctrl[name], value, controller);
+ }
+ if (isObjectEmpty(ctrl[name])) {
+ ctrl[name] = undefined;
+ }
+ }
+
+ function cachedToggleClass(className, switchValue) {
+ if (switchValue && !classCache[className]) {
+ $animate.addClass($element, className);
+ classCache[className] = true;
+ } else if (!switchValue && classCache[className]) {
+ $animate.removeClass($element, className);
+ classCache[className] = false;
+ }
+ }
+
+ function toggleValidationCss(validationErrorKey, isValid) {
+ validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
+
+ cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);
+ cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);
+ }
+}
+
+function isObjectEmpty(obj) {
+ if (obj) {
+ for (var prop in obj) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * @ngdoc directive
+ * @name ngNonBindable
+ * @restrict AC
+ * @priority 1000
+ *
+ * @description
+ * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
+ * DOM element. This is useful if the element contains what appears to be Angular directives and
+ * bindings but which should be ignored by Angular. This could be the case if you have a site that
+ * displays snippets of code, for instance.
+ *
+ * @element ANY
+ *
+ * @example
+ * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
+ * but the one wrapped in `ngNonBindable` is left alone.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div>Normal: {{1 + 2}}</div>
+ <div ng-non-bindable>Ignored: {{1 + 2}}</div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-non-bindable', function() {
+ expect(element(by.binding('1 + 2')).getText()).toContain('3');
+ expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
+ });
+ </file>
+ </example>
+ */
+var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
+
+/**
+ * @ngdoc directive
+ * @name ngPluralize
+ * @restrict EA
+ *
+ * @description
+ * `ngPluralize` is a directive that displays messages according to en-US localization rules.
+ * These rules are bundled with angular.js, but can be overridden
+ * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
+ * by specifying the mappings between
+ * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
+ * and the strings to be displayed.
+ *
+ * # Plural categories and explicit number rules
+ * There are two
+ * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
+ * in Angular's default en-US locale: "one" and "other".
+ *
+ * While a plural category may match many numbers (for example, in en-US locale, "other" can match
+ * any number that is not 1), an explicit number rule can only match one number. For example, the
+ * explicit number rule for "3" matches the number 3. There are examples of plural categories
+ * and explicit number rules throughout the rest of this documentation.
+ *
+ * # Configuring ngPluralize
+ * You configure ngPluralize by providing 2 attributes: `count` and `when`.
+ * You can also provide an optional attribute, `offset`.
+ *
+ * The value of the `count` attribute can be either a string or an {@link guide/expression
+ * Angular expression}; these are evaluated on the current scope for its bound value.
+ *
+ * The `when` attribute specifies the mappings between plural categories and the actual
+ * string to be displayed. The value of the attribute should be a JSON object.
+ *
+ * The following example shows how to configure ngPluralize:
+ *
+ * ```html
+ * <ng-pluralize count="personCount"
+ when="{'0': 'Nobody is viewing.',
+ * 'one': '1 person is viewing.',
+ * 'other': '{} people are viewing.'}">
+ * </ng-pluralize>
+ *```
+ *
+ * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
+ * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
+ * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
+ * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
+ * show "a dozen people are viewing".
+ *
+ * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
+ * into pluralized strings. In the previous example, Angular will replace `{}` with
+ * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
+ * for <span ng-non-bindable>{{numberExpression}}</span>.
+ *
+ * # Configuring ngPluralize with offset
+ * The `offset` attribute allows further customization of pluralized text, which can result in
+ * a better user experience. For example, instead of the message "4 people are viewing this document",
+ * you might display "John, Kate and 2 others are viewing this document".
+ * The offset attribute allows you to offset a number by any desired value.
+ * Let's take a look at an example:
+ *
+ * ```html
+ * <ng-pluralize count="personCount" offset=2
+ * when="{'0': 'Nobody is viewing.',
+ * '1': '{{person1}} is viewing.',
+ * '2': '{{person1}} and {{person2}} are viewing.',
+ * 'one': '{{person1}}, {{person2}} and one other person are viewing.',
+ * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
+ * </ng-pluralize>
+ * ```
+ *
+ * Notice that we are still using two plural categories(one, other), but we added
+ * three explicit number rules 0, 1 and 2.
+ * When one person, perhaps John, views the document, "John is viewing" will be shown.
+ * When three people view the document, no explicit number rule is found, so
+ * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
+ * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
+ * is shown.
+ *
+ * Note that when you specify offsets, you must provide explicit number rules for
+ * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
+ * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
+ * plural categories "one" and "other".
+ *
+ * @param {string|expression} count The variable to be bound to.
+ * @param {string} when The mapping between plural category to its corresponding strings.
+ * @param {number=} offset Offset to deduct from the total number.
+ *
+ * @example
+ <example module="pluralizeExample">
+ <file name="index.html">
+ <script>
+ angular.module('pluralizeExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.person1 = 'Igor';
+ $scope.person2 = 'Misko';
+ $scope.personCount = 1;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
+ Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
+ Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
+
+ <!--- Example with simple pluralization rules for en locale --->
+ Without Offset:
+ <ng-pluralize count="personCount"
+ when="{'0': 'Nobody is viewing.',
+ 'one': '1 person is viewing.',
+ 'other': '{} people are viewing.'}">
+ </ng-pluralize><br>
+
+ <!--- Example with offset --->
+ With Offset(2):
+ <ng-pluralize count="personCount" offset=2
+ when="{'0': 'Nobody is viewing.',
+ '1': '{{person1}} is viewing.',
+ '2': '{{person1}} and {{person2}} are viewing.',
+ 'one': '{{person1}}, {{person2}} and one other person are viewing.',
+ 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
+ </ng-pluralize>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should show correct pluralized string', function() {
+ var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
+ var withOffset = element.all(by.css('ng-pluralize')).get(1);
+ var countInput = element(by.model('personCount'));
+
+ expect(withoutOffset.getText()).toEqual('1 person is viewing.');
+ expect(withOffset.getText()).toEqual('Igor is viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('0');
+
+ expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
+ expect(withOffset.getText()).toEqual('Nobody is viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('2');
+
+ expect(withoutOffset.getText()).toEqual('2 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('3');
+
+ expect(withoutOffset.getText()).toEqual('3 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('4');
+
+ expect(withoutOffset.getText()).toEqual('4 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
+ });
+ it('should show data-bound names', function() {
+ var withOffset = element.all(by.css('ng-pluralize')).get(1);
+ var personCount = element(by.model('personCount'));
+ var person1 = element(by.model('person1'));
+ var person2 = element(by.model('person2'));
+ personCount.clear();
+ personCount.sendKeys('4');
+ person1.clear();
+ person1.sendKeys('Di');
+ person2.clear();
+ person2.sendKeys('Vojta');
+ expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
+ });
+ </file>
+ </example>
+ */
+var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
+ var BRACE = /{}/g,
+ IS_WHEN = /^when(Minus)?(.+)$/;
+
+ return {
+ restrict: 'EA',
+ link: function(scope, element, attr) {
+ var numberExp = attr.count,
+ whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
+ offset = attr.offset || 0,
+ whens = scope.$eval(whenExp) || {},
+ whensExpFns = {},
+ startSymbol = $interpolate.startSymbol(),
+ endSymbol = $interpolate.endSymbol(),
+ braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
+ watchRemover = angular.noop,
+ lastCount;
+
+ forEach(attr, function(expression, attributeName) {
+ var tmpMatch = IS_WHEN.exec(attributeName);
+ if (tmpMatch) {
+ var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
+ whens[whenKey] = element.attr(attr.$attr[attributeName]);
+ }
+ });
+ forEach(whens, function(expression, key) {
+ whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
+
+ });
+
+ scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
+ var count = parseFloat(newVal);
+ var countIsNaN = isNaN(count);
+
+ if (!countIsNaN && !(count in whens)) {
+ // If an explicit number rule such as 1, 2, 3... is defined, just use it.
+ // Otherwise, check it against pluralization rules in $locale service.
+ count = $locale.pluralCat(count - offset);
+ }
+
+ // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
+ // In JS `NaN !== NaN`, so we have to exlicitly check.
+ if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {
+ watchRemover();
+ watchRemover = scope.$watch(whensExpFns[count], updateElementText);
+ lastCount = count;
+ }
+ });
+
+ function updateElementText(newText) {
+ element.text(newText || '');
+ }
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngRepeat
+ *
+ * @description
+ * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
+ * instance gets its own scope, where the given loop variable is set to the current collection item,
+ * and `$index` is set to the item index or key.
+ *
+ * Special properties are exposed on the local scope of each template instance, including:
+ *
+ * | Variable | Type | Details |
+ * |-----------|-----------------|-----------------------------------------------------------------------------|
+ * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) |
+ * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. |
+ * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
+ * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. |
+ * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
+ * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
+ *
+ * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
+ * This may be useful when, for instance, nesting ngRepeats.
+ *
+ * # Iterating over object properties
+ *
+ * It is possible to get `ngRepeat` to iterate over the properties of an object using the following
+ * syntax:
+ *
+ * ```js
+ * <div ng-repeat="(key, value) in myObj"> ... </div>
+ * ```
+ *
+ * You need to be aware that the JavaScript specification does not define what order
+ * it will return the keys for an object. In order to have a guaranteed deterministic order
+ * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**.
+ *
+ * If this is not desired, the recommended workaround is to convert your object into an array
+ * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
+ * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)
+ * or implement a `$watch` on the object yourself.
+ *
+ * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the
+ * strategy of providing keys in the order in which they were defined, although there are exceptions
+ * when keys are deleted and reinstated.
+ *
+ *
+ * # Tracking and Duplicates
+ *
+ * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
+ *
+ * * When an item is added, a new instance of the template is added to the DOM.
+ * * When an item is removed, its template instance is removed from the DOM.
+ * * When items are reordered, their respective templates are reordered in the DOM.
+ *
+ * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
+ * there are duplicates, it is not possible to maintain a one-to-one mapping between collection
+ * items and DOM elements.
+ *
+ * If you do need to repeat duplicate items, you can substitute the default tracking behavior
+ * with your own using the `track by` expression.
+ *
+ * For example, you may track items by the index of each item in the collection, using the
+ * special scope property `$index`:
+ * ```html
+ * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
+ * {{n}}
+ * </div>
+ * ```
+ *
+ * You may use arbitrary expressions in `track by`, including references to custom functions
+ * on the scope:
+ * ```html
+ * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
+ * {{n}}
+ * </div>
+ * ```
+ *
+ * If you are working with objects that have an identifier property, you can track
+ * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
+ * will not have to rebuild the DOM elements for items it has already rendered, even if the
+ * JavaScript objects in the collection have been substituted for new ones:
+ * ```html
+ * <div ng-repeat="model in collection track by model.id">
+ * {{model.name}}
+ * </div>
+ * ```
+ *
+ * When no `track by` expression is provided, it is equivalent to tracking by the built-in
+ * `$id` function, which tracks items by their identity:
+ * ```html
+ * <div ng-repeat="obj in collection track by $id(obj)">
+ * {{obj.prop}}
+ * </div>
+ * ```
+ *
+ * # Special repeat start and end points
+ * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
+ * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
+ * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
+ * up to and including the ending HTML tag where **ng-repeat-end** is placed.
+ *
+ * The example below makes use of this feature:
+ * ```html
+ * <header ng-repeat-start="item in items">
+ * Header {{ item }}
+ * </header>
+ * <div class="body">
+ * Body {{ item }}
+ * </div>
+ * <footer ng-repeat-end>
+ * Footer {{ item }}
+ * </footer>
+ * ```
+ *
+ * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
+ * ```html
+ * <header>
+ * Header A
+ * </header>
+ * <div class="body">
+ * Body A
+ * </div>
+ * <footer>
+ * Footer A
+ * </footer>
+ * <header>
+ * Header B
+ * </header>
+ * <div class="body">
+ * Body B
+ * </div>
+ * <footer>
+ * Footer B
+ * </footer>
+ * ```
+ *
+ * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
+ * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
+ *
+ * @animations
+ * **.enter** - when a new item is added to the list or when an item is revealed after a filter
+ *
+ * **.leave** - when an item is removed from the list or when an item is filtered out
+ *
+ * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
+ *
+ * @element ANY
+ * @scope
+ * @priority 1000
+ * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
+ * formats are currently supported:
+ *
+ * * `variable in expression` – where variable is the user defined loop variable and `expression`
+ * is a scope expression giving the collection to enumerate.
+ *
+ * For example: `album in artist.albums`.
+ *
+ * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
+ * and `expression` is the scope expression giving the collection to enumerate.
+ *
+ * For example: `(name, age) in {'adam':10, 'amalie':12}`.
+ *
+ * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
+ * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
+ * is specified, ng-repeat associates elements by identity. It is an error to have
+ * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
+ * mapped to the same DOM element, which is not possible.) If filters are used in the expression, they should be
+ * applied before the tracking expression.
+ *
+ * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
+ * will be associated by item identity in the array.
+ *
+ * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
+ * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
+ * with the corresponding item in the array by identity. Moving the same object in array would move the DOM
+ * element in the same way in the DOM.
+ *
+ * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
+ * case the object identity does not matter. Two objects are considered equivalent as long as their `id`
+ * property is same.
+ *
+ * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
+ * to items in conjunction with a tracking expression.
+ *
+ * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
+ * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
+ * when a filter is active on the repeater, but the filtered result set is empty.
+ *
+ * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
+ * the items have been processed through the filter.
+ *
+ * @example
+ * This example initializes the scope to a list of names and
+ * then uses `ngRepeat` to display every person:
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-init="friends = [
+ {name:'John', age:25, gender:'boy'},
+ {name:'Jessie', age:30, gender:'girl'},
+ {name:'Johanna', age:28, gender:'girl'},
+ {name:'Joy', age:15, gender:'girl'},
+ {name:'Mary', age:28, gender:'girl'},
+ {name:'Peter', age:95, gender:'boy'},
+ {name:'Sebastian', age:50, gender:'boy'},
+ {name:'Erika', age:27, gender:'girl'},
+ {name:'Patrick', age:40, gender:'boy'},
+ {name:'Samantha', age:60, gender:'girl'}
+ ]">
+ I have {{friends.length}} friends. They are:
+ <input type="search" ng-model="q" placeholder="filter friends..." />
+ <ul class="example-animate-container">
+ <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
+ [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
+ </li>
+ <li class="animate-repeat" ng-if="results.length == 0">
+ <strong>No results found...</strong>
+ </li>
+ </ul>
+ </div>
+ </file>
+ <file name="animations.css">
+ .example-animate-container {
+ background:white;
+ border:1px solid black;
+ list-style:none;
+ margin:0;
+ padding:0 10px;
+ }
+
+ .animate-repeat {
+ line-height:40px;
+ list-style:none;
+ box-sizing:border-box;
+ }
+
+ .animate-repeat.ng-move,
+ .animate-repeat.ng-enter,
+ .animate-repeat.ng-leave {
+ -webkit-transition:all linear 0.5s;
+ transition:all linear 0.5s;
+ }
+
+ .animate-repeat.ng-leave.ng-leave-active,
+ .animate-repeat.ng-move,
+ .animate-repeat.ng-enter {
+ opacity:0;
+ max-height:0;
+ }
+
+ .animate-repeat.ng-leave,
+ .animate-repeat.ng-move.ng-move-active,
+ .animate-repeat.ng-enter.ng-enter-active {
+ opacity:1;
+ max-height:40px;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var friends = element.all(by.repeater('friend in friends'));
+
+ it('should render initial data set', function() {
+ expect(friends.count()).toBe(10);
+ expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
+ expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
+ expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
+ expect(element(by.binding('friends.length')).getText())
+ .toMatch("I have 10 friends. They are:");
+ });
+
+ it('should update repeater when filter predicate changes', function() {
+ expect(friends.count()).toBe(10);
+
+ element(by.model('q')).sendKeys('ma');
+
+ expect(friends.count()).toBe(2);
+ expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
+ expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
+ });
+ </file>
+ </example>
+ */
+var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
+ var NG_REMOVED = '$$NG_REMOVED';
+ var ngRepeatMinErr = minErr('ngRepeat');
+
+ var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {
+ // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
+ scope[valueIdentifier] = value;
+ if (keyIdentifier) scope[keyIdentifier] = key;
+ scope.$index = index;
+ scope.$first = (index === 0);
+ scope.$last = (index === (arrayLength - 1));
+ scope.$middle = !(scope.$first || scope.$last);
+ // jshint bitwise: false
+ scope.$odd = !(scope.$even = (index&1) === 0);
+ // jshint bitwise: true
+ };
+
+ var getBlockStart = function(block) {
+ return block.clone[0];
+ };
+
+ var getBlockEnd = function(block) {
+ return block.clone[block.clone.length - 1];
+ };
+
+
+ return {
+ restrict: 'A',
+ multiElement: true,
+ transclude: 'element',
+ priority: 1000,
+ terminal: true,
+ $$tlb: true,
+ compile: function ngRepeatCompile($element, $attr) {
+ var expression = $attr.ngRepeat;
+ var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');
+
+ var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
+
+ if (!match) {
+ throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
+ expression);
+ }
+
+ var lhs = match[1];
+ var rhs = match[2];
+ var aliasAs = match[3];
+ var trackByExp = match[4];
+
+ match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
+
+ if (!match) {
+ throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
+ lhs);
+ }
+ var valueIdentifier = match[3] || match[1];
+ var keyIdentifier = match[2];
+
+ if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
+ /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) {
+ throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
+ aliasAs);
+ }
+
+ var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;
+ var hashFnLocals = {$id: hashKey};
+
+ if (trackByExp) {
+ trackByExpGetter = $parse(trackByExp);
+ } else {
+ trackByIdArrayFn = function(key, value) {
+ return hashKey(value);
+ };
+ trackByIdObjFn = function(key) {
+ return key;
+ };
+ }
+
+ return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
+
+ if (trackByExpGetter) {
+ trackByIdExpFn = function(key, value, index) {
+ // assign key, value, and $index to the locals so that they can be used in hash functions
+ if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
+ hashFnLocals[valueIdentifier] = value;
+ hashFnLocals.$index = index;
+ return trackByExpGetter($scope, hashFnLocals);
+ };
+ }
+
+ // Store a list of elements from previous run. This is a hash where key is the item from the
+ // iterator, and the value is objects with following properties.
+ // - scope: bound scope
+ // - element: previous element.
+ // - index: position
+ //
+ // We are using no-proto object so that we don't need to guard against inherited props via
+ // hasOwnProperty.
+ var lastBlockMap = createMap();
+
+ //watch props
+ $scope.$watchCollection(rhs, function ngRepeatAction(collection) {
+ var index, length,
+ previousNode = $element[0], // node that cloned nodes should be inserted after
+ // initialized to the comment node anchor
+ nextNode,
+ // Same as lastBlockMap but it has the current state. It will become the
+ // lastBlockMap on the next iteration.
+ nextBlockMap = createMap(),
+ collectionLength,
+ key, value, // key/value of iteration
+ trackById,
+ trackByIdFn,
+ collectionKeys,
+ block, // last object information {scope, element, id}
+ nextBlockOrder,
+ elementsToRemove;
+
+ if (aliasAs) {
+ $scope[aliasAs] = collection;
+ }
+
+ if (isArrayLike(collection)) {
+ collectionKeys = collection;
+ trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
+ } else {
+ trackByIdFn = trackByIdExpFn || trackByIdObjFn;
+ // if object, extract keys, sort them and use to determine order of iteration over obj props
+ collectionKeys = [];
+ for (var itemKey in collection) {
+ if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') {
+ collectionKeys.push(itemKey);
+ }
+ }
+ collectionKeys.sort();
+ }
+
+ collectionLength = collectionKeys.length;
+ nextBlockOrder = new Array(collectionLength);
+
+ // locate existing items
+ for (index = 0; index < collectionLength; index++) {
+ key = (collection === collectionKeys) ? index : collectionKeys[index];
+ value = collection[key];
+ trackById = trackByIdFn(key, value, index);
+ if (lastBlockMap[trackById]) {
+ // found previously seen block
+ block = lastBlockMap[trackById];
+ delete lastBlockMap[trackById];
+ nextBlockMap[trackById] = block;
+ nextBlockOrder[index] = block;
+ } else if (nextBlockMap[trackById]) {
+ // if collision detected. restore lastBlockMap and throw an error
+ forEach(nextBlockOrder, function(block) {
+ if (block && block.scope) lastBlockMap[block.id] = block;
+ });
+ throw ngRepeatMinErr('dupes',
+ "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
+ expression, trackById, value);
+ } else {
+ // new never before seen block
+ nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
+ nextBlockMap[trackById] = true;
+ }
+ }
+
+ // remove leftover items
+ for (var blockKey in lastBlockMap) {
+ block = lastBlockMap[blockKey];
+ elementsToRemove = getBlockNodes(block.clone);
+ $animate.leave(elementsToRemove);
+ if (elementsToRemove[0].parentNode) {
+ // if the element was not removed yet because of pending animation, mark it as deleted
+ // so that we can ignore it later
+ for (index = 0, length = elementsToRemove.length; index < length; index++) {
+ elementsToRemove[index][NG_REMOVED] = true;
+ }
+ }
+ block.scope.$destroy();
+ }
+
+ // we are not using forEach for perf reasons (trying to avoid #call)
+ for (index = 0; index < collectionLength; index++) {
+ key = (collection === collectionKeys) ? index : collectionKeys[index];
+ value = collection[key];
+ block = nextBlockOrder[index];
+
+ if (block.scope) {
+ // if we have already seen this object, then we need to reuse the
+ // associated scope/element
+
+ nextNode = previousNode;
+
+ // skip nodes that are already pending removal via leave animation
+ do {
+ nextNode = nextNode.nextSibling;
+ } while (nextNode && nextNode[NG_REMOVED]);
+
+ if (getBlockStart(block) != nextNode) {
+ // existing item which got moved
+ $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
+ }
+ previousNode = getBlockEnd(block);
+ updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
+ } else {
+ // new item which we don't know about
+ $transclude(function ngRepeatTransclude(clone, scope) {
+ block.scope = scope;
+ // http://jsperf.com/clone-vs-createcomment
+ var endNode = ngRepeatEndComment.cloneNode(false);
+ clone[clone.length++] = endNode;
+
+ // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?
+ $animate.enter(clone, null, jqLite(previousNode));
+ previousNode = endNode;
+ // Note: We only need the first/last node of the cloned nodes.
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
+ // by a directive with templateUrl when its template arrives.
+ block.clone = clone;
+ nextBlockMap[block.id] = block;
+ updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
+ });
+ }
+ }
+ lastBlockMap = nextBlockMap;
+ });
+ };
+ }
+ };
+}];
+
+var NG_HIDE_CLASS = 'ng-hide';
+var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
+/**
+ * @ngdoc directive
+ * @name ngShow
+ *
+ * @description
+ * The `ngShow` directive shows or hides the given HTML element based on the expression
+ * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
+ * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
+ * in AngularJS and sets the display style to none (using an !important flag).
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```html
+ * <!-- when $scope.myValue is truthy (element is visible) -->
+ * <div ng-show="myValue"></div>
+ *
+ * <!-- when $scope.myValue is falsy (element is hidden) -->
+ * <div ng-show="myValue" class="ng-hide"></div>
+ * ```
+ *
+ * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class
+ * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed
+ * from the element causing the element not to appear hidden.
+ *
+ * ## Why is !important used?
+ *
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
+ * can be easily overridden by heavier selectors. For example, something as simple
+ * as changing the display style on a HTML list item would make hidden elements appear visible.
+ * This also becomes a bigger issue when dealing with CSS frameworks.
+ *
+ * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
+ * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
+ * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
+ *
+ * ### Overriding `.ng-hide`
+ *
+ * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
+ * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope
+ * with extra animation classes that can be added.
+ *
+ * ```css
+ * .ng-hide:not(.ng-hide-animate) {
+ * /&#42; this is just another form of hiding an element &#42;/
+ * display: block!important;
+ * position: absolute;
+ * top: -9999px;
+ * left: -9999px;
+ * }
+ * ```
+ *
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
+ *
+ * ## A note about animations with `ngShow`
+ *
+ * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
+ * is true and false. This system works like the animation system present with ngClass except that
+ * you must also include the !important flag to override the display property
+ * so that you can perform an animation when the element is hidden during the time of the animation.
+ *
+ * ```css
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ * /&#42; this is required as of 1.3x to properly
+ * apply all styling in a show/hide animation &#42;/
+ * transition: 0s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add-active,
+ * .my-element.ng-hide-remove-active {
+ * /&#42; the transition is defined in the active class &#42;/
+ * transition: 1s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * ```
+ *
+ * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
+ *
+ * @animations
+ * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
+ * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
+ *
+ * @element ANY
+ * @param {expression} ngShow If the {@link guide/expression expression} is truthy
+ * then the element is shown or hidden respectively.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked"><br/>
+ <div>
+ Show:
+ <div class="check-element animate-show" ng-show="checked">
+ <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
+ </div>
+ </div>
+ <div>
+ Hide:
+ <div class="check-element animate-show" ng-hide="checked">
+ <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
+ </div>
+ </div>
+ </file>
+ <file name="glyphicons.css">
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
+ </file>
+ <file name="animations.css">
+ .animate-show {
+ line-height: 20px;
+ opacity: 1;
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+
+ .animate-show.ng-hide-add.ng-hide-add-active,
+ .animate-show.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transition: all linear 0.5s;
+ transition: all linear 0.5s;
+ }
+
+ .animate-show.ng-hide {
+ line-height: 0;
+ opacity: 0;
+ padding: 0 10px;
+ }
+
+ .check-element {
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
+ var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
+
+ it('should check ng-show / ng-hide', function() {
+ expect(thumbsUp.isDisplayed()).toBeFalsy();
+ expect(thumbsDown.isDisplayed()).toBeTruthy();
+
+ element(by.model('checked')).click();
+
+ expect(thumbsUp.isDisplayed()).toBeTruthy();
+ expect(thumbsDown.isDisplayed()).toBeFalsy();
+ });
+ </file>
+ </example>
+ */
+var ngShowDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'A',
+ multiElement: true,
+ link: function(scope, element, attr) {
+ scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
+ // we're adding a temporary, animation-specific class for ng-hide since this way
+ // we can control when the element is actually displayed on screen without having
+ // to have a global/greedy CSS selector that breaks when other animations are run.
+ // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
+ $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
+ });
+ });
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngHide
+ *
+ * @description
+ * The `ngHide` directive shows or hides the given HTML element based on the expression
+ * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
+ * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
+ * in AngularJS and sets the display style to none (using an !important flag).
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```html
+ * <!-- when $scope.myValue is truthy (element is hidden) -->
+ * <div ng-hide="myValue" class="ng-hide"></div>
+ *
+ * <!-- when $scope.myValue is falsy (element is visible) -->
+ * <div ng-hide="myValue"></div>
+ * ```
+ *
+ * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class
+ * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed
+ * from the element causing the element not to appear hidden.
+ *
+ * ## Why is !important used?
+ *
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
+ * can be easily overridden by heavier selectors. For example, something as simple
+ * as changing the display style on a HTML list item would make hidden elements appear visible.
+ * This also becomes a bigger issue when dealing with CSS frameworks.
+ *
+ * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
+ * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
+ * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
+ *
+ * ### Overriding `.ng-hide`
+ *
+ * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
+ * class in CSS:
+ *
+ * ```css
+ * .ng-hide {
+ * /&#42; this is just another form of hiding an element &#42;/
+ * display: block!important;
+ * position: absolute;
+ * top: -9999px;
+ * left: -9999px;
+ * }
+ * ```
+ *
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
+ *
+ * ## A note about animations with `ngHide`
+ *
+ * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
+ * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
+ * CSS class is added and removed for you instead of your own CSS class.
+ *
+ * ```css
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ * transition: 0.5s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * ```
+ *
+ * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
+ *
+ * @animations
+ * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
+ * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
+ *
+ * @element ANY
+ * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
+ * the element is shown or hidden respectively.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked"><br/>
+ <div>
+ Show:
+ <div class="check-element animate-hide" ng-show="checked">
+ <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
+ </div>
+ </div>
+ <div>
+ Hide:
+ <div class="check-element animate-hide" ng-hide="checked">
+ <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
+ </div>
+ </div>
+ </file>
+ <file name="glyphicons.css">
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
+ </file>
+ <file name="animations.css">
+ .animate-hide {
+ -webkit-transition: all linear 0.5s;
+ transition: all linear 0.5s;
+ line-height: 20px;
+ opacity: 1;
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+
+ .animate-hide.ng-hide {
+ line-height: 0;
+ opacity: 0;
+ padding: 0 10px;
+ }
+
+ .check-element {
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
+ var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
+
+ it('should check ng-show / ng-hide', function() {
+ expect(thumbsUp.isDisplayed()).toBeFalsy();
+ expect(thumbsDown.isDisplayed()).toBeTruthy();
+
+ element(by.model('checked')).click();
+
+ expect(thumbsUp.isDisplayed()).toBeTruthy();
+ expect(thumbsDown.isDisplayed()).toBeFalsy();
+ });
+ </file>
+ </example>
+ */
+var ngHideDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'A',
+ multiElement: true,
+ link: function(scope, element, attr) {
+ scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
+ // The comment inside of the ngShowDirective explains why we add and
+ // remove a temporary class for the show/hide animation
+ $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
+ });
+ });
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngStyle
+ * @restrict AC
+ *
+ * @description
+ * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
+ *
+ * @element ANY
+ * @param {expression} ngStyle
+ *
+ * {@link guide/expression Expression} which evals to an
+ * object whose keys are CSS style names and values are corresponding values for those CSS
+ * keys.
+ *
+ * Since some CSS style names are not valid keys for an object, they must be quoted.
+ * See the 'background-color' style in the example below.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input type="button" value="set color" ng-click="myStyle={color:'red'}">
+ <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
+ <input type="button" value="clear" ng-click="myStyle={}">
+ <br/>
+ <span ng-style="myStyle">Sample Text</span>
+ <pre>myStyle={{myStyle}}</pre>
+ </file>
+ <file name="style.css">
+ span {
+ color: black;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var colorSpan = element(by.css('span'));
+
+ it('should check ng-style', function() {
+ expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
+ element(by.css('input[value=\'set color\']')).click();
+ expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
+ element(by.css('input[value=clear]')).click();
+ expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
+ });
+ </file>
+ </example>
+ */
+var ngStyleDirective = ngDirective(function(scope, element, attr) {
+ scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
+ if (oldStyles && (newStyles !== oldStyles)) {
+ forEach(oldStyles, function(val, style) { element.css(style, '');});
+ }
+ if (newStyles) element.css(newStyles);
+ }, true);
+});
+
+/**
+ * @ngdoc directive
+ * @name ngSwitch
+ * @restrict EA
+ *
+ * @description
+ * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
+ * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
+ * as specified in the template.
+ *
+ * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
+ * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
+ * matches the value obtained from the evaluated expression. In other words, you define a container element
+ * (where you place the directive), place an expression on the **`on="..."` attribute**
+ * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
+ * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
+ * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
+ * attribute is displayed.
+ *
+ * <div class="alert alert-info">
+ * Be aware that the attribute values to match against cannot be expressions. They are interpreted
+ * as literal string values to match against.
+ * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
+ * value of the expression `$scope.someVal`.
+ * </div>
+
+ * @animations
+ * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
+ * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
+ *
+ * @usage
+ *
+ * ```
+ * <ANY ng-switch="expression">
+ * <ANY ng-switch-when="matchValue1">...</ANY>
+ * <ANY ng-switch-when="matchValue2">...</ANY>
+ * <ANY ng-switch-default>...</ANY>
+ * </ANY>
+ * ```
+ *
+ *
+ * @scope
+ * @priority 1200
+ * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
+ * On child elements add:
+ *
+ * * `ngSwitchWhen`: the case statement to match against. If match then this
+ * case will be displayed. If the same match appears multiple times, all the
+ * elements will be displayed.
+ * * `ngSwitchDefault`: the default case when no other case match. If there
+ * are multiple default cases, all of them will be displayed when no other
+ * case match.
+ *
+ *
+ * @example
+ <example module="switchExample" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <select ng-model="selection" ng-options="item for item in items">
+ </select>
+ <code>selection={{selection}}</code>
+ <hr/>
+ <div class="animate-switch-container"
+ ng-switch on="selection">
+ <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
+ <div class="animate-switch" ng-switch-when="home">Home Span</div>
+ <div class="animate-switch" ng-switch-default>default</div>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('switchExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.items = ['settings', 'home', 'other'];
+ $scope.selection = $scope.items[0];
+ }]);
+ </file>
+ <file name="animations.css">
+ .animate-switch-container {
+ position:relative;
+ background:white;
+ border:1px solid black;
+ height:40px;
+ overflow:hidden;
+ }
+
+ .animate-switch {
+ padding:10px;
+ }
+
+ .animate-switch.ng-animate {
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+
+ position:absolute;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ }
+
+ .animate-switch.ng-leave.ng-leave-active,
+ .animate-switch.ng-enter {
+ top:-50px;
+ }
+ .animate-switch.ng-leave,
+ .animate-switch.ng-enter.ng-enter-active {
+ top:0;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var switchElem = element(by.css('[ng-switch]'));
+ var select = element(by.model('selection'));
+
+ it('should start in settings', function() {
+ expect(switchElem.getText()).toMatch(/Settings Div/);
+ });
+ it('should change to home', function() {
+ select.all(by.css('option')).get(1).click();
+ expect(switchElem.getText()).toMatch(/Home Span/);
+ });
+ it('should select default', function() {
+ select.all(by.css('option')).get(2).click();
+ expect(switchElem.getText()).toMatch(/default/);
+ });
+ </file>
+ </example>
+ */
+var ngSwitchDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'EA',
+ require: 'ngSwitch',
+
+ // asks for $scope to fool the BC controller module
+ controller: ['$scope', function ngSwitchController() {
+ this.cases = {};
+ }],
+ link: function(scope, element, attr, ngSwitchController) {
+ var watchExpr = attr.ngSwitch || attr.on,
+ selectedTranscludes = [],
+ selectedElements = [],
+ previousLeaveAnimations = [],
+ selectedScopes = [];
+
+ var spliceFactory = function(array, index) {
+ return function() { array.splice(index, 1); };
+ };
+
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
+ var i, ii;
+ for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {
+ $animate.cancel(previousLeaveAnimations[i]);
+ }
+ previousLeaveAnimations.length = 0;
+
+ for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
+ var selected = getBlockNodes(selectedElements[i].clone);
+ selectedScopes[i].$destroy();
+ var promise = previousLeaveAnimations[i] = $animate.leave(selected);
+ promise.then(spliceFactory(previousLeaveAnimations, i));
+ }
+
+ selectedElements.length = 0;
+ selectedScopes.length = 0;
+
+ if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
+ forEach(selectedTranscludes, function(selectedTransclude) {
+ selectedTransclude.transclude(function(caseElement, selectedScope) {
+ selectedScopes.push(selectedScope);
+ var anchor = selectedTransclude.element;
+ caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');
+ var block = { clone: caseElement };
+
+ selectedElements.push(block);
+ $animate.enter(caseElement, anchor.parent(), anchor);
+ });
+ });
+ }
+ });
+ }
+ };
+}];
+
+var ngSwitchWhenDirective = ngDirective({
+ transclude: 'element',
+ priority: 1200,
+ require: '^ngSwitch',
+ multiElement: true,
+ link: function(scope, element, attrs, ctrl, $transclude) {
+ ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
+ ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
+ }
+});
+
+var ngSwitchDefaultDirective = ngDirective({
+ transclude: 'element',
+ priority: 1200,
+ require: '^ngSwitch',
+ multiElement: true,
+ link: function(scope, element, attr, ctrl, $transclude) {
+ ctrl.cases['?'] = (ctrl.cases['?'] || []);
+ ctrl.cases['?'].push({ transclude: $transclude, element: element });
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngTransclude
+ * @restrict EAC
+ *
+ * @description
+ * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
+ *
+ * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
+ *
+ * @element ANY
+ *
+ * @example
+ <example module="transcludeExample">
+ <file name="index.html">
+ <script>
+ angular.module('transcludeExample', [])
+ .directive('pane', function(){
+ return {
+ restrict: 'E',
+ transclude: true,
+ scope: { title:'@' },
+ template: '<div style="border: 1px solid black;">' +
+ '<div style="background-color: gray">{{title}}</div>' +
+ '<ng-transclude></ng-transclude>' +
+ '</div>'
+ };
+ })
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.title = 'Lorem Ipsum';
+ $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input ng-model="title"> <br/>
+ <textarea ng-model="text"></textarea> <br/>
+ <pane title="{{title}}">{{text}}</pane>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should have transcluded', function() {
+ var titleElement = element(by.model('title'));
+ titleElement.clear();
+ titleElement.sendKeys('TITLE');
+ var textElement = element(by.model('text'));
+ textElement.clear();
+ textElement.sendKeys('TEXT');
+ expect(element(by.binding('title')).getText()).toEqual('TITLE');
+ expect(element(by.binding('text')).getText()).toEqual('TEXT');
+ });
+ </file>
+ </example>
+ *
+ */
+var ngTranscludeDirective = ngDirective({
+ restrict: 'EAC',
+ link: function($scope, $element, $attrs, controller, $transclude) {
+ if (!$transclude) {
+ throw minErr('ngTransclude')('orphan',
+ 'Illegal use of ngTransclude directive in the template! ' +
+ 'No parent directive that requires a transclusion found. ' +
+ 'Element: {0}',
+ startingTag($element));
+ }
+
+ $transclude(function(clone) {
+ $element.empty();
+ $element.append(clone);
+ });
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name script
+ * @restrict E
+ *
+ * @description
+ * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
+ * template can be used by {@link ng.directive:ngInclude `ngInclude`},
+ * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
+ * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
+ * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
+ *
+ * @param {string} type Must be set to `'text/ng-template'`.
+ * @param {string} id Cache name of the template.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <script type="text/ng-template" id="/tpl.html">
+ Content of the template.
+ </script>
+
+ <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
+ <div id="tpl-content" ng-include src="currentTpl"></div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should load template defined inside script tag', function() {
+ element(by.css('#tpl-link')).click();
+ expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
+ });
+ </file>
+ </example>
+ */
+var scriptDirective = ['$templateCache', function($templateCache) {
+ return {
+ restrict: 'E',
+ terminal: true,
+ compile: function(element, attr) {
+ if (attr.type == 'text/ng-template') {
+ var templateUrl = attr.id,
+ text = element[0].text;
+
+ $templateCache.put(templateUrl, text);
+ }
+ }
+ };
+}];
+
+var ngOptionsMinErr = minErr('ngOptions');
+/**
+ * @ngdoc directive
+ * @name select
+ * @restrict E
+ *
+ * @description
+ * HTML `SELECT` element with angular data-binding.
+ *
+ * # `ngOptions`
+ *
+ * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
+ * elements for the `<select>` element using the array or object obtained by evaluating the
+ * `ngOptions` comprehension expression.
+ *
+ * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
+ * similar result. However, `ngOptions` provides some benefits such as reducing memory and
+ * increasing speed by not creating a new scope for each repeated instance, as well as providing
+ * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
+ * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
+ * to a non-string value. This is because an option element can only be bound to string values at
+ * present.
+ *
+ * When an item in the `<select>` menu is selected, the array element or object property
+ * represented by the selected option will be bound to the model identified by the `ngModel`
+ * directive.
+ *
+ * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
+ * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
+ * option. See example below for demonstration.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
+ * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
+ * </div>
+ *
+ * ## `select` **`as`**
+ *
+ * Using `select` **`as`** will bind the result of the `select` expression to the model, but
+ * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
+ * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
+ * is used, the result of that expression will be set as the value of the `option` and `select` elements.
+ *
+ *
+ * ### `select` **`as`** and **`track by`**
+ *
+ * <div class="alert alert-warning">
+ * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
+ * </div>
+ *
+ * Consider the following example:
+ *
+ * ```html
+ * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
+ * ```
+ *
+ * ```js
+ * $scope.values = [{
+ * id: 1,
+ * label: 'aLabel',
+ * subItem: { name: 'aSubItem' }
+ * }, {
+ * id: 2,
+ * label: 'bLabel',
+ * subItem: { name: 'bSubItem' }
+ * }];
+ *
+ * $scope.selected = { name: 'aSubItem' };
+ * ```
+ *
+ * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
+ * of the data source (to `item` in this example). To calculate whether an element is selected, we do the
+ * following:
+ *
+ * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
+ * 2. Apply **`track by`** to the already selected value in `ngModel`.
+ * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
+ * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
+ * a wrong object, the selected element can't be found, `<select>` is always reset to the "not
+ * selected" option.
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required The control is considered valid only if value is entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {comprehension_expression=} ngOptions in one of the following forms:
+ *
+ * * for array data sources:
+ * * `label` **`for`** `value` **`in`** `array`
+ * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
+ * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
+ * (for including a filter with `track by`)
+ * * for object data sources:
+ * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
+ * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
+ * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
+ * * `select` **`as`** `label` **`group by`** `group`
+ * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
+ *
+ * Where:
+ *
+ * * `array` / `object`: an expression which evaluates to an array / object to iterate over.
+ * * `value`: local variable which will refer to each item in the `array` or each property value
+ * of `object` during iteration.
+ * * `key`: local variable which will refer to a property name in `object` during iteration.
+ * * `label`: The result of this expression will be the label for `<option>` element. The
+ * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
+ * * `select`: The result of this expression will be bound to the model of the parent `<select>`
+ * element. If not specified, `select` expression will default to `value`.
+ * * `group`: The result of this expression will be used to group options using the `<optgroup>`
+ * DOM element.
+ * * `trackexpr`: Used when working with an array of objects. The result of this expression will be
+ * used to identify the objects in the array. The `trackexpr` will most likely refer to the
+ * `value` variable (e.g. `value.propertyName`). With this the selection is preserved
+ * even when the options are recreated (e.g. reloaded from the server).
+ *
+ * @example
+ <example module="selectExample">
+ <file name="index.html">
+ <script>
+ angular.module('selectExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.colors = [
+ {name:'black', shade:'dark'},
+ {name:'white', shade:'light'},
+ {name:'red', shade:'dark'},
+ {name:'blue', shade:'dark'},
+ {name:'yellow', shade:'light'}
+ ];
+ $scope.myColor = $scope.colors[2]; // red
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <ul>
+ <li ng-repeat="color in colors">
+ Name: <input ng-model="color.name">
+ [<a href ng-click="colors.splice($index, 1)">X</a>]
+ </li>
+ <li>
+ [<a href ng-click="colors.push({})">add</a>]
+ </li>
+ </ul>
+ <hr/>
+ Color (null not allowed):
+ <select ng-model="myColor" ng-options="color.name for color in colors"></select><br>
+
+ Color (null allowed):
+ <span class="nullable">
+ <select ng-model="myColor" ng-options="color.name for color in colors">
+ <option value="">-- choose color --</option>
+ </select>
+ </span><br/>
+
+ Color grouped by shade:
+ <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
+ </select><br/>
+
+
+ Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
+ <hr/>
+ Currently selected: {{ {selected_color:myColor} }}
+ <div style="border:solid 1px black; height:20px"
+ ng-style="{'background-color':myColor.name}">
+ </div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-options', function() {
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
+ element.all(by.model('myColor')).first().click();
+ element.all(by.css('select[ng-model="myColor"] option')).first().click();
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
+ element(by.css('.nullable select[ng-model="myColor"]')).click();
+ element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
+ });
+ </file>
+ </example>
+ */
+
+var ngOptionsDirective = valueFn({
+ restrict: 'A',
+ terminal: true
+});
+
+// jshint maxlen: false
+var selectDirective = ['$compile', '$parse', function($compile, $parse) {
+ //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
+ var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
+ nullModelCtrl = {$setViewValue: noop};
+// jshint maxlen: 100
+
+ return {
+ restrict: 'E',
+ require: ['select', '?ngModel'],
+ controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
+ var self = this,
+ optionsMap = {},
+ ngModelCtrl = nullModelCtrl,
+ nullOption,
+ unknownOption;
+
+
+ self.databound = $attrs.ngModel;
+
+
+ self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {
+ ngModelCtrl = ngModelCtrl_;
+ nullOption = nullOption_;
+ unknownOption = unknownOption_;
+ };
+
+
+ self.addOption = function(value, element) {
+ assertNotHasOwnProperty(value, '"option value"');
+ optionsMap[value] = true;
+
+ if (ngModelCtrl.$viewValue == value) {
+ $element.val(value);
+ if (unknownOption.parent()) unknownOption.remove();
+ }
+ // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
+ // Adding an <option selected="selected"> element to a <select required="required"> should
+ // automatically select the new element
+ if (element && element[0].hasAttribute('selected')) {
+ element[0].selected = true;
+ }
+ };
+
+
+ self.removeOption = function(value) {
+ if (this.hasOption(value)) {
+ delete optionsMap[value];
+ if (ngModelCtrl.$viewValue === value) {
+ this.renderUnknownOption(value);
+ }
+ }
+ };
+
+
+ self.renderUnknownOption = function(val) {
+ var unknownVal = '? ' + hashKey(val) + ' ?';
+ unknownOption.val(unknownVal);
+ $element.prepend(unknownOption);
+ $element.val(unknownVal);
+ unknownOption.prop('selected', true); // needed for IE
+ };
+
+
+ self.hasOption = function(value) {
+ return optionsMap.hasOwnProperty(value);
+ };
+
+ $scope.$on('$destroy', function() {
+ // disable unknown option so that we don't do work when the whole select is being destroyed
+ self.renderUnknownOption = noop;
+ });
+ }],
+
+ link: function(scope, element, attr, ctrls) {
+ // if ngModel is not defined, we don't need to do anything
+ if (!ctrls[1]) return;
+
+ var selectCtrl = ctrls[0],
+ ngModelCtrl = ctrls[1],
+ multiple = attr.multiple,
+ optionsExp = attr.ngOptions,
+ nullOption = false, // if false, user will not be able to select it (used by ngOptions)
+ emptyOption,
+ renderScheduled = false,
+ // we can't just jqLite('<option>') since jqLite is not smart enough
+ // to create it in <select> and IE barfs otherwise.
+ optionTemplate = jqLite(document.createElement('option')),
+ optGroupTemplate =jqLite(document.createElement('optgroup')),
+ unknownOption = optionTemplate.clone();
+
+ // find "null" option
+ for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
+ if (children[i].value === '') {
+ emptyOption = nullOption = children.eq(i);
+ break;
+ }
+ }
+
+ selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
+
+ // required validator
+ if (multiple) {
+ ngModelCtrl.$isEmpty = function(value) {
+ return !value || value.length === 0;
+ };
+ }
+
+ if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
+ else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);
+ else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);
+
+
+ ////////////////////////////
+
+
+
+ function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
+ ngModelCtrl.$render = function() {
+ var viewValue = ngModelCtrl.$viewValue;
+
+ if (selectCtrl.hasOption(viewValue)) {
+ if (unknownOption.parent()) unknownOption.remove();
+ selectElement.val(viewValue);
+ if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
+ } else {
+ if (viewValue == null && emptyOption) {
+ selectElement.val('');
+ } else {
+ selectCtrl.renderUnknownOption(viewValue);
+ }
+ }
+ };
+
+ selectElement.on('change', function() {
+ scope.$apply(function() {
+ if (unknownOption.parent()) unknownOption.remove();
+ ngModelCtrl.$setViewValue(selectElement.val());
+ });
+ });
+ }
+
+ function setupAsMultiple(scope, selectElement, ctrl) {
+ var lastView;
+ ctrl.$render = function() {
+ var items = new HashMap(ctrl.$viewValue);
+ forEach(selectElement.find('option'), function(option) {
+ option.selected = isDefined(items.get(option.value));
+ });
+ };
+
+ // we have to do it on each watch since ngModel watches reference, but
+ // we need to work of an array, so we need to see if anything was inserted/removed
+ scope.$watch(function selectMultipleWatch() {
+ if (!equals(lastView, ctrl.$viewValue)) {
+ lastView = shallowCopy(ctrl.$viewValue);
+ ctrl.$render();
+ }
+ });
+
+ selectElement.on('change', function() {
+ scope.$apply(function() {
+ var array = [];
+ forEach(selectElement.find('option'), function(option) {
+ if (option.selected) {
+ array.push(option.value);
+ }
+ });
+ ctrl.$setViewValue(array);
+ });
+ });
+ }
+
+ function setupAsOptions(scope, selectElement, ctrl) {
+ var match;
+
+ if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {
+ throw ngOptionsMinErr('iexp',
+ "Expected expression in form of " +
+ "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
+ " but got '{0}'. Element: {1}",
+ optionsExp, startingTag(selectElement));
+ }
+
+ var displayFn = $parse(match[2] || match[1]),
+ valueName = match[4] || match[6],
+ selectAs = / as /.test(match[0]) && match[1],
+ selectAsFn = selectAs ? $parse(selectAs) : null,
+ keyName = match[5],
+ groupByFn = $parse(match[3] || ''),
+ valueFn = $parse(match[2] ? match[1] : valueName),
+ valuesFn = $parse(match[7]),
+ track = match[8],
+ trackFn = track ? $parse(match[8]) : null,
+ trackKeysCache = {},
+ // This is an array of array of existing option groups in DOM.
+ // We try to reuse these if possible
+ // - optionGroupsCache[0] is the options with no option group
+ // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
+ optionGroupsCache = [[{element: selectElement, label:''}]],
+ //re-usable object to represent option's locals
+ locals = {};
+
+ if (nullOption) {
+ // compile the element since there might be bindings in it
+ $compile(nullOption)(scope);
+
+ // remove the class, which is added automatically because we recompile the element and it
+ // becomes the compilation root
+ nullOption.removeClass('ng-scope');
+
+ // we need to remove it before calling selectElement.empty() because otherwise IE will
+ // remove the label from the element. wtf?
+ nullOption.remove();
+ }
+
+ // clear contents, we'll add what's needed based on the model
+ selectElement.empty();
+
+ selectElement.on('change', selectionChanged);
+
+ ctrl.$render = render;
+
+ scope.$watchCollection(valuesFn, scheduleRendering);
+ scope.$watchCollection(getLabels, scheduleRendering);
+
+ if (multiple) {
+ scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering);
+ }
+
+ // ------------------------------------------------------------------ //
+
+ function callExpression(exprFn, key, value) {
+ locals[valueName] = value;
+ if (keyName) locals[keyName] = key;
+ return exprFn(scope, locals);
+ }
+
+ function selectionChanged() {
+ scope.$apply(function() {
+ var collection = valuesFn(scope) || [];
+ var viewValue;
+ if (multiple) {
+ viewValue = [];
+ forEach(selectElement.val(), function(selectedKey) {
+ selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;
+ viewValue.push(getViewValue(selectedKey, collection[selectedKey]));
+ });
+ } else {
+ var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();
+ viewValue = getViewValue(selectedKey, collection[selectedKey]);
+ }
+ ctrl.$setViewValue(viewValue);
+ render();
+ });
+ }
+
+ function getViewValue(key, value) {
+ if (key === '?') {
+ return undefined;
+ } else if (key === '') {
+ return null;
+ } else {
+ var viewValueFn = selectAsFn ? selectAsFn : valueFn;
+ return callExpression(viewValueFn, key, value);
+ }
+ }
+
+ function getLabels() {
+ var values = valuesFn(scope);
+ var toDisplay;
+ if (values && isArray(values)) {
+ toDisplay = new Array(values.length);
+ for (var i = 0, ii = values.length; i < ii; i++) {
+ toDisplay[i] = callExpression(displayFn, i, values[i]);
+ }
+ return toDisplay;
+ } else if (values) {
+ // TODO: Add a test for this case
+ toDisplay = {};
+ for (var prop in values) {
+ if (values.hasOwnProperty(prop)) {
+ toDisplay[prop] = callExpression(displayFn, prop, values[prop]);
+ }
+ }
+ }
+ return toDisplay;
+ }
+
+ function createIsSelectedFn(viewValue) {
+ var selectedSet;
+ if (multiple) {
+ if (trackFn && isArray(viewValue)) {
+
+ selectedSet = new HashMap([]);
+ for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {
+ // tracking by key
+ selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);
+ }
+ } else {
+ selectedSet = new HashMap(viewValue);
+ }
+ } else if (trackFn) {
+ viewValue = callExpression(trackFn, null, viewValue);
+ }
+
+ return function isSelected(key, value) {
+ var compareValueFn;
+ if (trackFn) {
+ compareValueFn = trackFn;
+ } else if (selectAsFn) {
+ compareValueFn = selectAsFn;
+ } else {
+ compareValueFn = valueFn;
+ }
+
+ if (multiple) {
+ return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));
+ } else {
+ return viewValue === callExpression(compareValueFn, key, value);
+ }
+ };
+ }
+
+ function scheduleRendering() {
+ if (!renderScheduled) {
+ scope.$$postDigest(render);
+ renderScheduled = true;
+ }
+ }
+
+ /**
+ * A new labelMap is created with each render.
+ * This function is called for each existing option with added=false,
+ * and each new option with added=true.
+ * - Labels that are passed to this method twice,
+ * (once with added=true and once with added=false) will end up with a value of 0, and
+ * will cause no change to happen to the corresponding option.
+ * - Labels that are passed to this method only once with added=false will end up with a
+ * value of -1 and will eventually be passed to selectCtrl.removeOption()
+ * - Labels that are passed to this method only once with added=true will end up with a
+ * value of 1 and will eventually be passed to selectCtrl.addOption()
+ */
+ function updateLabelMap(labelMap, label, added) {
+ labelMap[label] = labelMap[label] || 0;
+ labelMap[label] += (added ? 1 : -1);
+ }
+
+ function render() {
+ renderScheduled = false;
+
+ // Temporary location for the option groups before we render them
+ var optionGroups = {'':[]},
+ optionGroupNames = [''],
+ optionGroupName,
+ optionGroup,
+ option,
+ existingParent, existingOptions, existingOption,
+ viewValue = ctrl.$viewValue,
+ values = valuesFn(scope) || [],
+ keys = keyName ? sortedKeys(values) : values,
+ key,
+ value,
+ groupLength, length,
+ groupIndex, index,
+ labelMap = {},
+ selected,
+ isSelected = createIsSelectedFn(viewValue),
+ anySelected = false,
+ lastElement,
+ element,
+ label,
+ optionId;
+
+ trackKeysCache = {};
+
+ // We now build up the list of options we need (we merge later)
+ for (index = 0; length = keys.length, index < length; index++) {
+ key = index;
+ if (keyName) {
+ key = keys[index];
+ if (key.charAt(0) === '$') continue;
+ }
+ value = values[key];
+
+ optionGroupName = callExpression(groupByFn, key, value) || '';
+ if (!(optionGroup = optionGroups[optionGroupName])) {
+ optionGroup = optionGroups[optionGroupName] = [];
+ optionGroupNames.push(optionGroupName);
+ }
+
+ selected = isSelected(key, value);
+ anySelected = anySelected || selected;
+
+ label = callExpression(displayFn, key, value); // what will be seen by the user
+
+ // doing displayFn(scope, locals) || '' overwrites zero values
+ label = isDefined(label) ? label : '';
+ optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);
+ if (trackFn) {
+ trackKeysCache[optionId] = key;
+ }
+
+ optionGroup.push({
+ // either the index into array or key from object
+ id: optionId,
+ label: label,
+ selected: selected // determine if we should be selected
+ });
+ }
+ if (!multiple) {
+ if (nullOption || viewValue === null) {
+ // insert null option if we have a placeholder, or the model is null
+ optionGroups[''].unshift({id:'', label:'', selected:!anySelected});
+ } else if (!anySelected) {
+ // option could not be found, we have to insert the undefined item
+ optionGroups[''].unshift({id:'?', label:'', selected:true});
+ }
+ }
+
+ // Now we need to update the list of DOM nodes to match the optionGroups we computed above
+ for (groupIndex = 0, groupLength = optionGroupNames.length;
+ groupIndex < groupLength;
+ groupIndex++) {
+ // current option group name or '' if no group
+ optionGroupName = optionGroupNames[groupIndex];
+
+ // list of options for that group. (first item has the parent)
+ optionGroup = optionGroups[optionGroupName];
+
+ if (optionGroupsCache.length <= groupIndex) {
+ // we need to grow the optionGroups
+ existingParent = {
+ element: optGroupTemplate.clone().attr('label', optionGroupName),
+ label: optionGroup.label
+ };
+ existingOptions = [existingParent];
+ optionGroupsCache.push(existingOptions);
+ selectElement.append(existingParent.element);
+ } else {
+ existingOptions = optionGroupsCache[groupIndex];
+ existingParent = existingOptions[0]; // either SELECT (no group) or OPTGROUP element
+
+ // update the OPTGROUP label if not the same.
+ if (existingParent.label != optionGroupName) {
+ existingParent.element.attr('label', existingParent.label = optionGroupName);
+ }
+ }
+
+ lastElement = null; // start at the beginning
+ for (index = 0, length = optionGroup.length; index < length; index++) {
+ option = optionGroup[index];
+ if ((existingOption = existingOptions[index + 1])) {
+ // reuse elements
+ lastElement = existingOption.element;
+ if (existingOption.label !== option.label) {
+ updateLabelMap(labelMap, existingOption.label, false);
+ updateLabelMap(labelMap, option.label, true);
+ lastElement.text(existingOption.label = option.label);
+ lastElement.prop('label', existingOption.label);
+ }
+ if (existingOption.id !== option.id) {
+ lastElement.val(existingOption.id = option.id);
+ }
+ // lastElement.prop('selected') provided by jQuery has side-effects
+ if (lastElement[0].selected !== option.selected) {
+ lastElement.prop('selected', (existingOption.selected = option.selected));
+ if (msie) {
+ // See #7692
+ // The selected item wouldn't visually update on IE without this.
+ // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well
+ lastElement.prop('selected', existingOption.selected);
+ }
+ }
+ } else {
+ // grow elements
+
+ // if it's a null option
+ if (option.id === '' && nullOption) {
+ // put back the pre-compiled element
+ element = nullOption;
+ } else {
+ // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but
+ // in this version of jQuery on some browser the .text() returns a string
+ // rather then the element.
+ (element = optionTemplate.clone())
+ .val(option.id)
+ .prop('selected', option.selected)
+ .attr('selected', option.selected)
+ .prop('label', option.label)
+ .text(option.label);
+ }
+
+ existingOptions.push(existingOption = {
+ element: element,
+ label: option.label,
+ id: option.id,
+ selected: option.selected
+ });
+ updateLabelMap(labelMap, option.label, true);
+ if (lastElement) {
+ lastElement.after(element);
+ } else {
+ existingParent.element.append(element);
+ }
+ lastElement = element;
+ }
+ }
+ // remove any excessive OPTIONs in a group
+ index++; // increment since the existingOptions[0] is parent element not OPTION
+ while (existingOptions.length > index) {
+ option = existingOptions.pop();
+ updateLabelMap(labelMap, option.label, false);
+ option.element.remove();
+ }
+ }
+ // remove any excessive OPTGROUPs from select
+ while (optionGroupsCache.length > groupIndex) {
+ // remove all the labels in the option group
+ optionGroup = optionGroupsCache.pop();
+ for (index = 1; index < optionGroup.length; ++index) {
+ updateLabelMap(labelMap, optionGroup[index].label, false);
+ }
+ optionGroup[0].element.remove();
+ }
+ forEach(labelMap, function(count, label) {
+ if (count > 0) {
+ selectCtrl.addOption(label);
+ } else if (count < 0) {
+ selectCtrl.removeOption(label);
+ }
+ });
+ }
+ }
+ }
+ };
+}];
+
+var optionDirective = ['$interpolate', function($interpolate) {
+ var nullSelectCtrl = {
+ addOption: noop,
+ removeOption: noop
+ };
+
+ return {
+ restrict: 'E',
+ priority: 100,
+ compile: function(element, attr) {
+ if (isUndefined(attr.value)) {
+ var interpolateFn = $interpolate(element.text(), true);
+ if (!interpolateFn) {
+ attr.$set('value', element.text());
+ }
+ }
+
+ return function(scope, element, attr) {
+ var selectCtrlName = '$selectController',
+ parent = element.parent(),
+ selectCtrl = parent.data(selectCtrlName) ||
+ parent.parent().data(selectCtrlName); // in case we are in optgroup
+
+ if (!selectCtrl || !selectCtrl.databound) {
+ selectCtrl = nullSelectCtrl;
+ }
+
+ if (interpolateFn) {
+ scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
+ attr.$set('value', newVal);
+ if (oldVal !== newVal) {
+ selectCtrl.removeOption(oldVal);
+ }
+ selectCtrl.addOption(newVal, element);
+ });
+ } else {
+ selectCtrl.addOption(attr.value, element);
+ }
+
+ element.on('$destroy', function() {
+ selectCtrl.removeOption(attr.value);
+ });
+ };
+ }
+ };
+}];
+
+var styleDirective = valueFn({
+ restrict: 'E',
+ terminal: false
+});
+
+var requiredDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+ attr.required = true; // force truthy in case we are on non input element
+
+ ctrl.$validators.required = function(modelValue, viewValue) {
+ return !attr.required || !ctrl.$isEmpty(viewValue);
+ };
+
+ attr.$observe('required', function() {
+ ctrl.$validate();
+ });
+ }
+ };
+};
+
+
+var patternDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var regexp, patternExp = attr.ngPattern || attr.pattern;
+ attr.$observe('pattern', function(regex) {
+ if (isString(regex) && regex.length > 0) {
+ regex = new RegExp('^' + regex + '$');
+ }
+
+ if (regex && !regex.test) {
+ throw minErr('ngPattern')('noregexp',
+ 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
+ regex, startingTag(elm));
+ }
+
+ regexp = regex || undefined;
+ ctrl.$validate();
+ });
+
+ ctrl.$validators.pattern = function(modelValue, viewValue) {
+ // HTML5 pattern constraint validates the input value, so we validate the viewValue
+ return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
+ };
+ }
+ };
+};
+
+
+var maxlengthDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var maxlength = -1;
+ attr.$observe('maxlength', function(value) {
+ var intVal = int(value);
+ maxlength = isNaN(intVal) ? -1 : intVal;
+ ctrl.$validate();
+ });
+ ctrl.$validators.maxlength = function(modelValue, viewValue) {
+ return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
+ };
+ }
+ };
+};
+
+var minlengthDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var minlength = 0;
+ attr.$observe('minlength', function(value) {
+ minlength = int(value) || 0;
+ ctrl.$validate();
+ });
+ ctrl.$validators.minlength = function(modelValue, viewValue) {
+ return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
+ };
+ }
+ };
+};
+
+ if (window.angular.bootstrap) {
+ //AngularJS is already loaded, so we can return here...
+ console.log('WARNING: Tried to load angular more than once.');
+ return;
+ }
+
+ //try to bind to jquery now so that one can write jqLite(document).ready()
+ //but we will rebind on bootstrap again.
+ bindJQuery();
+
+ publishExternalAPI(angular);
+
+ jqLite(document).ready(function() {
+ angularInit(document, bootstrap);
+ });
+
+})(window, document);
+
+!window.angular.$$csp() && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>'); \ No newline at end of file
diff --git a/afb-client/bower_components/angular/angular.min.js b/afb-client/bower_components/angular/angular.min.js
new file mode 100644
index 0000000..8dcf6e0
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.min.js
@@ -0,0 +1,253 @@
+/*
+ AngularJS v1.3.20
+ (c) 2010-2014 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(R,W,u){'use strict';function S(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.3.20/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ta(b){if(null==b||Ua(b))return!1;var a="length"in Object(b)&&b.length;
+return b.nodeType===qa&&a?!0:x(b)||H(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function r(b,a,c){var d,e;if(b)if(z(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(H(b)||Ta(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==r)b.forEach(a,c,b);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d,b);return b}function Ed(b,a,c){for(var d=Object.keys(b).sort(),
+e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function lc(b){return function(a,c){b(c,a)}}function Fd(){return++rb}function mc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function w(b){for(var a=b.$$hashKey,c=1,d=arguments.length;c<d;c++){var e=arguments[c];if(e)for(var f=Object.keys(e),g=0,h=f.length;g<h;g++){var l=f[g];b[l]=e[l]}}mc(b,a);return b}function aa(b){return parseInt(b,10)}function Ob(b,a){return w(Object.create(b),a)}function A(){}function ra(b){return b}function ea(b){return function(){return b}}
+function D(b){return"undefined"===typeof b}function y(b){return"undefined"!==typeof b}function L(b){return null!==b&&"object"===typeof b}function x(b){return"string"===typeof b}function Y(b){return"number"===typeof b}function ha(b){return"[object Date]"===Ca.call(b)}function z(b){return"function"===typeof b}function Va(b){return"[object RegExp]"===Ca.call(b)}function Ua(b){return b&&b.window===b}function Wa(b){return b&&b.$evalAsync&&b.$watch}function Xa(b){return"boolean"===typeof b}function nc(b){return!(!b||
+!(b.nodeName||b.prop&&b.attr&&b.find))}function Gd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function wa(b){return K(b.nodeName||b[0]&&b[0].nodeName)}function Ya(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return a}function Da(b,a,c,d){if(Ua(b)||Wa(b))throw Ja("cpws");if(a){if(b===a)throw Ja("cpi");c=c||[];d=d||[];if(L(b)){var e=c.indexOf(b);if(-1!==e)return d[e];c.push(b);d.push(a)}if(H(b))for(var f=a.length=0;f<b.length;f++)e=Da(b[f],null,c,d),L(b[f])&&(c.push(b[f]),
+d.push(e)),a.push(e);else{var g=a.$$hashKey;H(a)?a.length=0:r(a,function(b,c){delete a[c]});for(f in b)b.hasOwnProperty(f)&&(e=Da(b[f],null,c,d),L(b[f])&&(c.push(b[f]),d.push(e)),a[f]=e);mc(a,g)}}else if(a=b)H(b)?a=Da(b,[],c,d):ha(b)?a=new Date(b.getTime()):Va(b)?(a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex):L(b)&&(e=Object.create(Object.getPrototypeOf(b)),a=Da(b,e,c,d));return a}function sa(b,a){if(H(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(L(b))for(c in a=
+a||{},b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ia(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(H(b)){if(!H(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ia(b[d],a[d]))return!1;return!0}}else{if(ha(b))return ha(a)?ia(b.getTime(),a.getTime()):!1;if(Va(b))return Va(a)?b.toString()==a.toString():!1;if(Wa(b)||Wa(a)||Ua(b)||Ua(a)||H(a)||ha(a)||Va(a))return!1;c={};for(d in b)if("$"!==
+d.charAt(0)&&!z(b[d])){if(!ia(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c.hasOwnProperty(d)&&"$"!==d.charAt(0)&&a[d]!==u&&!z(a[d]))return!1;return!0}return!1}function Za(b,a,c){return b.concat($a.call(a,c))}function oc(b,a){var c=2<arguments.length?$a.call(arguments,2):[];return!z(a)||a instanceof RegExp?a:c.length?function(){return arguments.length?a.apply(b,Za(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Hd(b,a){var c=a;"string"===typeof b&&
+"$"===b.charAt(0)&&"$"===b.charAt(1)?c=u:Ua(a)?c="$WINDOW":a&&W===a?c="$DOCUMENT":Wa(a)&&(c="$SCOPE");return c}function ab(b,a){if("undefined"===typeof b)return u;Y(a)||(a=a?2:null);return JSON.stringify(b,Hd,a)}function pc(b){return x(b)?JSON.parse(b):b}function xa(b){b=B(b).clone();try{b.empty()}catch(a){}var c=B("<div>").append(b).html();try{return b[0].nodeType===bb?K(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+K(b)})}catch(d){return K(c)}}function qc(b){try{return decodeURIComponent(b)}catch(a){}}
+function rc(b){var a={},c,d;r((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,"%20").split("="),d=qc(c[0]),y(d)&&(b=y(c[1])?qc(c[1]):!0,sc.call(a,d)?H(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Pb(b){var a=[];r(b,function(b,d){H(b)?r(b,function(b){a.push(Ea(d,!0)+(!0===b?"":"="+Ea(b,!0)))}):a.push(Ea(d,!0)+(!0===b?"":"="+Ea(b,!0)))});return a.length?a.join("&"):""}function sb(b){return Ea(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Ea(b,a){return encodeURIComponent(b).replace(/%40/gi,
+"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Id(b,a){var c,d,e=tb.length;b=B(b);for(d=0;d<e;++d)if(c=tb[d]+a,x(c=b.attr(c)))return c;return null}function Jd(b,a){var c,d,e={};r(tb,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});r(tb,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Id(c,"strict-di"),
+a(c,d?[d]:[],e))}function tc(b,a,c){L(c)||(c={});c=w({strictDi:!1},c);var d=function(){b=B(b);if(b.injector()){var d=b[0]===W?"document":xa(b);throw Ja("btstrpd",d.replace(/</,"&lt;").replace(/>/,"&gt;"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=cb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",
+d);c(b)(a)})}]);return d},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;R&&e.test(R.name)&&(c.debugInfoEnabled=!0,R.name=R.name.replace(e,""));if(R&&!f.test(R.name))return d();R.name=R.name.replace(f,"");ca.resumeBootstrap=function(b){r(b,function(b){a.push(b)});return d()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function Kd(){R.name="NG_ENABLE_DEBUG_INFO!"+R.name;R.location.reload()}function Ld(b){b=ca.element(b).injector();if(!b)throw Ja("test");return b.get("$$testability")}
+function uc(b,a){a=a||"_";return b.replace(Md,function(b,d){return(d?a:"")+b.toLowerCase()})}function Nd(){var b;vc||((ta=R.jQuery)&&ta.fn.on?(B=ta,w(ta.fn,{scope:Ka.scope,isolateScope:Ka.isolateScope,controller:Ka.controller,injector:Ka.injector,inheritedData:Ka.inheritedData}),b=ta.cleanData,ta.cleanData=function(a){var c;if(Qb)Qb=!1;else for(var d=0,e;null!=(e=a[d]);d++)(c=ta._data(e,"events"))&&c.$destroy&&ta(e).triggerHandler("$destroy");b(a)}):B=T,ca.element=B,vc=!0)}function Rb(b,a,c){if(!b)throw Ja("areq",
+a||"?",c||"required");return b}function La(b,a,c){c&&H(b)&&(b=b[b.length-1]);Rb(z(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ma(b,a){if("hasOwnProperty"===b)throw Ja("badname",a);}function wc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&z(b)?oc(e,b):b}function ub(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!==b);return B(c)}function ja(){return Object.create(null)}
+function Od(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=S("$injector"),d=S("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||S;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(c,d,e,f){f||(f=b);return function(){f[e||"push"]([c,d,arguments]);return t}}if(!g)throw c("nomod",f);var b=[],d=[],e=[],q=a("$injector","invoke","push",d),t={_invokeQueue:b,_configBlocks:d,
+_runBlocks:e,requires:g,name:f,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:q,run:function(a){e.push(a);return this}};h&&q(h);return t})}})}function Pd(b){w(b,{bootstrap:tc,copy:Da,extend:w,equals:ia,
+element:B,forEach:r,injector:cb,noop:A,bind:oc,toJson:ab,fromJson:pc,identity:ra,isUndefined:D,isDefined:y,isString:x,isFunction:z,isObject:L,isNumber:Y,isElement:nc,isArray:H,version:Qd,isDate:ha,lowercase:K,uppercase:vb,callbacks:{counter:0},getTestability:Ld,$$minErr:S,$$csp:db,reloadWithDebugInfo:Kd});eb=Od(R);try{eb("ngLocale")}catch(a){eb("ngLocale",[]).provider("$locale",Rd)}eb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:Sd});a.provider("$compile",xc).directive({a:Td,
+input:yc,textarea:yc,form:Ud,script:Vd,select:Wd,style:Xd,option:Yd,ngBind:Zd,ngBindHtml:$d,ngBindTemplate:ae,ngClass:be,ngClassEven:ce,ngClassOdd:de,ngCloak:ee,ngController:fe,ngForm:ge,ngHide:he,ngIf:ie,ngInclude:je,ngInit:ke,ngNonBindable:le,ngPluralize:me,ngRepeat:ne,ngShow:oe,ngStyle:pe,ngSwitch:qe,ngSwitchWhen:re,ngSwitchDefault:se,ngOptions:te,ngTransclude:ue,ngModel:ve,ngList:we,ngChange:xe,pattern:zc,ngPattern:zc,required:Ac,ngRequired:Ac,minlength:Bc,ngMinlength:Bc,maxlength:Cc,ngMaxlength:Cc,
+ngValue:ye,ngModelOptions:ze}).directive({ngInclude:Ae}).directive(wb).directive(Dc);a.provider({$anchorScroll:Be,$animate:Ce,$browser:De,$cacheFactory:Ee,$controller:Fe,$document:Ge,$exceptionHandler:He,$filter:Ec,$interpolate:Ie,$interval:Je,$http:Ke,$httpBackend:Le,$location:Me,$log:Ne,$parse:Oe,$rootScope:Pe,$q:Qe,$$q:Re,$sce:Se,$sceDelegate:Te,$sniffer:Ue,$templateCache:Ve,$templateRequest:We,$$testability:Xe,$timeout:Ye,$window:Ze,$$rAF:$e,$$asyncCallback:af,$$jqLite:bf})}])}function fb(b){return b.replace(cf,
+function(a,b,d,e){return e?d.toUpperCase():d}).replace(df,"Moz$1")}function Fc(b){b=b.nodeType;return b===qa||!b||9===b}function Gc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Sb.test(b)){c=c||e.appendChild(a.createElement("div"));d=(ef.exec(b)||["",""])[1].toLowerCase();d=ka[d]||ka._default;c.innerHTML=d[1]+b.replace(ff,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=Za(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";r(f,function(a){e.appendChild(a)});
+return e}function T(b){if(b instanceof T)return b;var a;x(b)&&(b=N(b),a=!0);if(!(this instanceof T)){if(a&&"<"!=b.charAt(0))throw Tb("nosel");return new T(b)}if(a){a=W;var c;b=(c=gf.exec(b))?[a.createElement(c[1])]:(c=Gc(b,a))?c.childNodes:[]}Hc(this,b)}function Ub(b){return b.cloneNode(!0)}function xb(b,a){a||yb(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)yb(c[d])}function Ic(b,a,c,d){if(y(d))throw Tb("offargs");var e=(d=zb(b))&&d.events,f=d&&d.handle;if(f)if(a)r(a.split(" "),
+function(a){if(y(c)){var d=e[a];Ya(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a,f,!1),delete e[a]}function yb(b,a){var c=b.ng339,d=c&&Ab[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Ic(b)),delete Ab[c],b.ng339=u))}function zb(b,a){var c=b.ng339,c=c&&Ab[c];a&&!c&&(b.ng339=c=++hf,c=Ab[c]={events:{},data:{},handle:u});return c}function Vb(b,a,c){if(Fc(b)){var d=y(c),e=!d&&a&&!L(a),
+f=!a;b=(b=zb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];w(b,a)}}}function Bb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function Cb(b,a){a&&b.setAttribute&&r(a.split(" "),function(a){b.setAttribute("class",N((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+N(a)+" "," ")))})}function Db(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");
+r(a.split(" "),function(a){a=N(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",N(c))}}function Hc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c=a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Jc(b,a){return Eb(b,"$"+(a||"ngController")+"Controller")}function Eb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=H(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=B.data(b,a[d]))!==u)return c;b=b.parentNode||
+11===b.nodeType&&b.host}}function Kc(b){for(xb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Lc(b,a){a||xb(b);var c=b.parentNode;c&&c.removeChild(b)}function jf(b,a){a=a||R;if("complete"===a.document.readyState)a.setTimeout(b);else B(a).on("load",b)}function Mc(b,a){var c=Fb[a.toLowerCase()];return c&&Nc[wa(b)]&&c}function kf(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Oc[a]}function lf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=
+a[e||c.type],g=f?f.length:0;if(g){if(D(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=sa(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function bf(){this.$get=function(){return w(T,{hasClass:function(b,a){b.attr&&(b=b[0]);
+return Bb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return Db(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return Cb(b,a)}})}}function Na(b,a){var c=b&&b.$$hashKey;if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Fd)():c+":"+b}function gb(b,a){if(a){var c=0;this.nextUid=function(){return++c}}r(b,this.put,this)}function mf(b){return(b=b.toString().replace(Pc,"").match(Qc))?"function("+(b[1]||"").replace(/[\s\r\n]+/,
+" ")+")":"fn"}function cb(b,a){function c(a){return function(b,c){if(L(b))r(b,lc(a));else return a(b,c)}}function d(a,b){Ma(a,"service");if(z(b)||H(b))b=q.instantiate(b);if(!b.$get)throw Fa("pget",a);return p[a+"Provider"]=b}function e(a,b){return function(){var c=s.invoke(b,this);if(D(c))throw Fa("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;r(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=q.get(e[0]);f[e[1]].apply(f,
+e[2])}}if(!n.get(a)){n.put(a,!0);try{x(a)?(c=eb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(q.invoke(a)):H(a)?b.push(q.invoke(a)):La(a,"module")}catch(e){throw H(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Fa("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Fa("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a),
+b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var k=[],l=cb.$$annotate(b,a,g),h,q,p;q=0;for(h=l.length;q<h;q++){p=l[q];if("string"!==typeof p)throw Fa("itkn",p);k.push(f&&f.hasOwnProperty(p)?f[p]:d(p,g))}H(b)&&(b=b[h]);return b.apply(c,k)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((H(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return L(a)||z(a)?a:d},get:d,annotate:cb.$$annotate,has:function(a){return p.hasOwnProperty(a+
+"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],n=new gb([],!0),p={$provide:{provider:c(d),factory:c(f),service:c(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ea(b),!1)}),constant:c(function(a,b){Ma(a,"constant");p[a]=b;t[a]=b}),decorator:function(a,b){var c=q.get(a+"Provider"),d=c.$get;c.$get=function(){var a=s.invoke(d,c);return s.invoke(b,null,{$delegate:a})}}}},q=p.$injector=h(p,function(a,b){ca.isString(b)&&k.push(b);
+throw Fa("unpr",k.join(" <- "));}),t={},s=t.$injector=h(t,function(a,b){var c=q.get(a+"Provider",b);return s.invoke(c.$get,c,u,a)});r(g(b),function(a){s.invoke(a||A)});return s}function Be(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===wa(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():nc(c)?(c=c[0],c="fixed"!==
+a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):Y(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0,0)}function g(){var a=c.hash(),b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||jf(function(){d.$evalAsync(g)})});return g}]}function af(){this.$get=["$$rAF","$timeout",function(b,a){return b.supported?function(a){return b(a)}:
+function(b){return a(b,0,!1)}}]}function nf(b,a,c,d){function e(a){try{a.apply(null,$a.call(arguments,1))}finally{if(m--,0===m)for(;C.length;)try{C.pop()()}catch(b){c.error(b)}}}function f(a,b){(function da(){r($,function(a){a()});I=b(da,a)})()}function g(){h();l()}function h(){a:{try{M=t.state;break a}catch(a){}M=void 0}M=D(M)?null:M;ia(M,P)&&(M=P);P=M}function l(){if(G!==n.url()||E!==M)G=n.url(),E=M,r(X,function(a){a(n.url(),M)})}function k(a){try{return decodeURIComponent(a)}catch(b){return a}}
+var n=this,p=a[0],q=b.location,t=b.history,s=b.setTimeout,F=b.clearTimeout,v={};n.isMock=!1;var m=0,C=[];n.$$completeOutstandingRequest=e;n.$$incOutstandingRequestCount=function(){m++};n.notifyWhenNoOutstandingRequests=function(a){r($,function(a){a()});0===m?a():C.push(a)};var $=[],I;n.addPollFn=function(a){D(I)&&f(100,s);$.push(a);return a};var M,E,G=q.href,O=a.find("base"),Q=null;h();E=M;n.url=function(a,c,e){D(e)&&(e=null);q!==b.location&&(q=b.location);t!==b.history&&(t=b.history);if(a){var f=
+E===e;if(G===a&&(!d.history||f))return n;var g=G&&Ga(G)===Ga(a);G=a;E=e;if(!d.history||g&&f){if(!g||Q)Q=a;c?q.replace(a):g?(c=q,e=a.indexOf("#"),a=-1===e?"":a.substr(e),c.hash=a):q.href=a}else t[c?"replaceState":"pushState"](e,"",a),h(),E=M;return n}return Q||q.href.replace(/%27/g,"'")};n.state=function(){return M};var X=[],ba=!1,P=null;n.onUrlChange=function(a){if(!ba){if(d.history)B(b).on("popstate",g);B(b).on("hashchange",g);ba=!0}X.push(a);return a};n.$$checkUrlChange=l;n.baseHref=function(){var a=
+O.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};var fa={},y="",la=n.baseHref();n.cookies=function(a,b){var d,e,f,g;if(a)b===u?p.cookie=encodeURIComponent(a)+"=;path="+la+";expires=Thu, 01 Jan 1970 00:00:00 GMT":x(b)&&(d=(p.cookie=encodeURIComponent(a)+"="+encodeURIComponent(b)+";path="+la).length+1,4096<d&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"));else{if(p.cookie!==y)for(y=p.cookie,d=y.split("; "),fa={},f=0;f<d.length;f++)e=
+d[f],g=e.indexOf("="),0<g&&(a=k(e.substring(0,g)),fa[a]===u&&(fa[a]=k(e.substring(g+1))));return fa}};n.defer=function(a,b){var c;m++;c=s(function(){delete v[c];e(a)},b||0);v[c]=!0;return c};n.defer.cancel=function(a){return v[a]?(delete v[a],F(a),e(A),!0):!1}}function De(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new nf(b,d,a,c)}]}function Ee(){this.$get=function(){function b(b,d){function e(a){a!=p&&(q?q==a&&(q=a.n):q=a,f(a.n,a.p),f(a,p),p=a,p.n=null)}function f(a,
+b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw S("$cacheFactory")("iid",b);var g=0,h=w({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,n={},p=null,q=null;return a[b]={put:function(a,b){if(k<Number.MAX_VALUE){var c=n[a]||(n[a]={key:a});e(c)}if(!D(b))return a in l||g++,l[a]=b,g>k&&this.remove(q.key),b},get:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;b==p&&(p=b.p);b==q&&(q=b.n);f(b.n,b.p);delete n[a]}delete l[a];
+g--},removeAll:function(){l={};g=0;n={};p=q=null},destroy:function(){n=h=l=null;delete a[b]},info:function(){return w({},h,{size:g})}}}var a={};b.info=function(){var b={};r(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function Ve(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function xc(b,a){function c(a,b){var c=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,d={};r(a,function(a,e){var f=a.match(c);if(!f)throw ma("iscp",b,e,a);d[e]={mode:f[1][0],collection:"*"===
+f[2],optional:"?"===f[3],attrName:f[4]||e}});return d}var d={},e=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,f=/(([\w\-]+)(?:\:([^;]+))?;?)/,g=Gd("ngSrc,ngSrcset,src,srcset"),h=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,l=/^(on[a-z]+|formaction)$/;this.directive=function p(a,e){Ma(a,"directive");x(a)?(Rb(e,"directiveFactory"),d.hasOwnProperty(a)||(d[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,e){var f=[];r(d[a],function(d,g){try{var h=b.invoke(d);z(h)?h={compile:ea(h)}:!h.compile&&h.link&&
+(h.compile=ea(h.link));h.priority=h.priority||0;h.index=g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";L(h.scope)&&(h.$$isolateBindings=c(h.scope,h.name));f.push(h)}catch(l){e(l)}});return f}])),d[a].push(e)):r(a,lc(p));return this};this.aHrefSanitizationWhitelist=function(b){return y(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};
+var k=!0;this.debugInfoEnabled=function(a){return y(a)?(k=a,this):k};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,s,F,v,m,C,$,I,M){function E(a,b){try{a.addClass(b)}catch(c){}}function G(a,b,c,d,e){a instanceof B||(a=B(a));r(a,function(b,c){b.nodeType==bb&&b.nodeValue.match(/\S+/)&&(a[c]=B(b).wrap("<span></span>").parent()[0])});var f=O(a,b,a,c,d,e);G.$$addScopeClass(a);
+var g=null;return function(b,c,d){Rb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==wa(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?B(Xb(g,B("<div>").append(a).html())):c?Ka.clone.call(a):a;if(h)for(var l in h)d.data("$"+l+"Controller",h[l].instance);G.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function O(a,b,c,d,e,f){function g(a,
+c,d,e){var f,l,k,q,p,s,t;if(m)for(t=Array(c.length),q=0;q<h.length;q+=3)f=h[q],t[f]=c[f];else t=c;q=0;for(p=h.length;q<p;)l=t[h[q++]],c=h[q++],f=h[q++],c?(c.scope?(k=a.$new(),G.$$addScopeInfo(B(l),k)):k=a,s=c.transcludeOnThisElement?Q(a,c.transclude,e,c.elementTranscludeOnThisElement):!c.templateOnThisElement&&e?e:!e&&b?Q(a,b):null,c(f,k,l,d,s)):f&&f(a,l.childNodes,u,e)}for(var h=[],l,k,q,p,m,s=0;s<a.length;s++){l=new Yb;k=X(a[s],[],l,0===s?d:u,e);(f=k.length?fa(k,a[s],l,b,c,null,[],[],f):null)&&
+f.scope&&G.$$addScopeClass(l.$$element);l=f&&f.terminal||!(q=a[s].childNodes)||!q.length?null:O(q,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||l)h.push(s,f,l),p=!0,m=m||f;f=null}return p?g:null}function Q(a,b,c,d){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function X(a,b,c,d,g){var h=c.$attr,l;switch(a.nodeType){case qa:la(b,ya(wa(a)),"E",d,g);for(var k,
+q,p,m=a.attributes,s=0,t=m&&m.length;s<t;s++){var M=!1,I=!1;k=m[s];l=k.name;q=N(k.value);k=ya(l);if(p=U.test(k))l=l.replace(Rc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var F=k.replace(/(Start|End)$/,"");D(F)&&k===F+"Start"&&(M=l,I=l.substr(0,l.length-5)+"end",l=l.substr(0,l.length-6));k=ya(l.toLowerCase());h[k]=l;if(p||!c.hasOwnProperty(k))c[k]=q,Mc(a,k)&&(c[k]=!0);Pa(a,b,q,k,p);la(b,k,"A",d,g,M,I)}a=a.className;L(a)&&(a=a.animVal);if(x(a)&&""!==a)for(;l=f.exec(a);)k=ya(l[2]),
+la(b,k,"C",d,g)&&(c[k]=N(l[3])),a=a.substr(l.index+l[0].length);break;case bb:za(b,a.nodeValue);break;case 8:try{if(l=e.exec(a.nodeValue))k=ya(l[1]),la(b,k,"M",d,g)&&(c[k]=N(l[2]))}catch(v){}}b.sort(da);return b}function ba(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ma("uterdir",b,c);a.nodeType==qa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return B(d)}function P(a,b,c){return function(d,e,f,g,h){e=ba(e[0],
+b,c);return a(d,e,f,g,h)}}function fa(a,d,e,f,g,l,k,p,m){function s(a,b,c,d){if(a){c&&(a=P(a,c,d));a.require=J.require;a.directiveName=da;if(Q===J||J.$$isolateScope)a=Y(a,{isolateScope:!0});k.push(a)}if(b){c&&(b=P(b,c,d));b.require=J.require;b.directiveName=da;if(Q===J||J.$$isolateScope)b=Y(b,{isolateScope:!0});p.push(b)}}function M(a,b,c,d){var e,f="data",g=!1,l=c,k;if(x(b)){k=b.match(h);b=b.substring(k[0].length);k[3]&&(k[1]?k[3]=null:k[1]=k[3]);"^"===k[1]?f="inheritedData":"^^"===k[1]&&(f="inheritedData",
+l=c.parent());"?"===k[2]&&(g=!0);e=null;d&&"data"===f&&(e=d[b])&&(e=e.instance);e=e||l[f]("$"+b+"Controller");if(!e&&!g)throw ma("ctreq",b,a);return e||null}H(b)&&(e=[],r(b,function(b){e.push(M(a,b,c,d))}));return e}function I(a,c,f,g,l){function h(a,b,c){var d;Wa(a)||(c=b,b=a,a=u);A&&(d=C);c||(c=A?X.parent():X);return l(a,b,d,c,Wb)}var m,s,t,E,C,ib,X,P;d===f?(P=e,X=e.$$element):(X=B(f),P=new Yb(X,e));Q&&(E=c.$new(!0));l&&(ib=h,ib.$$boundTransclude=l);O&&($={},C={},r(O,function(a){var b={$scope:a===
+Q||a.$$isolateScope?E:c,$element:X,$attrs:P,$transclude:ib};t=a.controller;"@"==t&&(t=P[a.name]);b=v(t,b,!0,a.controllerAs);C[a.name]=b;A||X.data("$"+a.name+"Controller",b.instance);$[a.name]=b}));if(Q){G.$$addScopeInfo(X,E,!0,!(na&&(na===Q||na===Q.$$originalDirective)));G.$$addScopeClass(X,!0);g=$&&$[Q.name];var ba=E;g&&g.identifier&&!0===Q.bindToController&&(ba=g.instance);r(E.$$isolateBindings=Q.$$isolateBindings,function(a,d){var e=a.attrName,f=a.optional,g,l,h,k;switch(a.mode){case "@":P.$observe(e,
+function(a){ba[d]=a});P.$$observers[e].$$scope=c;P[e]&&(ba[d]=b(P[e])(c));break;case "=":if(f&&!P[e])break;l=F(P[e]);k=l.literal?ia:function(a,b){return a===b||a!==a&&b!==b};h=l.assign||function(){g=ba[d]=l(c);throw ma("nonassign",P[e],Q.name);};g=ba[d]=l(c);f=function(a){k(a,ba[d])||(k(a,g)?h(c,a=ba[d]):ba[d]=a);return g=a};f.$stateful=!0;f=a.collection?c.$watchCollection(P[e],f):c.$watch(F(P[e],f),null,l.literal);E.$on("$destroy",f);break;case "&":l=F(P[e]),ba[d]=function(a){return l(c,a)}}})}$&&
+(r($,function(a){a()}),$=null);g=0;for(m=k.length;g<m;g++)s=k[g],Z(s,s.isolateScope?E:c,X,P,s.require&&M(s.directiveName,s.require,X,C),ib);var Wb=c;Q&&(Q.template||null===Q.templateUrl)&&(Wb=E);a&&a(Wb,f.childNodes,u,l);for(g=p.length-1;0<=g;g--)s=p[g],Z(s,s.isolateScope?E:c,X,P,s.require&&M(s.directiveName,s.require,X,C),ib)}m=m||{};for(var E=-Number.MAX_VALUE,C,O=m.controllerDirectives,$,Q=m.newIsolateScopeDirective,na=m.templateDirective,fa=m.nonTlbTranscludeDirective,la=!1,D=!1,A=m.hasElementTranscludeDirective,
+w=e.$$element=B(d),J,da,V,hb=f,za,K=0,R=a.length;K<R;K++){J=a[K];var Pa=J.$$start,U=J.$$end;Pa&&(w=ba(d,Pa,U));V=u;if(E>J.priority)break;if(V=J.scope)J.templateUrl||(L(V)?(Oa("new/isolated scope",Q||C,J,w),Q=J):Oa("new/isolated scope",Q,J,w)),C=C||J;da=J.name;!J.templateUrl&&J.controller&&(V=J.controller,O=O||{},Oa("'"+da+"' controller",O[da],J,w),O[da]=J);if(V=J.transclude)la=!0,J.$$tlb||(Oa("transclusion",fa,J,w),fa=J),"element"==V?(A=!0,E=J.priority,V=w,w=e.$$element=B(W.createComment(" "+da+": "+
+e[da]+" ")),d=w[0],T(g,$a.call(V,0),d),hb=G(V,f,E,l&&l.name,{nonTlbTranscludeDirective:fa})):(V=B(Ub(d)).contents(),w.empty(),hb=G(V,f));if(J.template)if(D=!0,Oa("template",na,J,w),na=J,V=z(J.template)?J.template(w,e):J.template,V=Sc(V),J.replace){l=J;V=Sb.test(V)?Tc(Xb(J.templateNamespace,N(V))):[];d=V[0];if(1!=V.length||d.nodeType!==qa)throw ma("tplrt",da,"");T(g,w,d);R={$attr:{}};V=X(d,[],R);var aa=a.splice(K+1,a.length-(K+1));Q&&y(V);a=a.concat(V).concat(aa);S(e,R);R=a.length}else w.html(V);if(J.templateUrl)D=
+!0,Oa("template",na,J,w),na=J,J.replace&&(l=J),I=of(a.splice(K,a.length-K),w,e,g,la&&hb,k,p,{controllerDirectives:O,newIsolateScopeDirective:Q,templateDirective:na,nonTlbTranscludeDirective:fa}),R=a.length;else if(J.compile)try{za=J.compile(w,e,hb),z(za)?s(null,za,Pa,U):za&&s(za.pre,za.post,Pa,U)}catch(pf){c(pf,xa(w))}J.terminal&&(I.terminal=!0,E=Math.max(E,J.priority))}I.scope=C&&!0===C.scope;I.transcludeOnThisElement=la;I.elementTranscludeOnThisElement=A;I.templateOnThisElement=D;I.transclude=hb;
+m.hasElementTranscludeDirective=A;return I}function y(a){for(var b=0,c=a.length;b<c;b++)a[b]=Ob(a[b],{$$isolateScope:!0})}function la(b,e,f,g,l,h,k){if(e===l)return null;l=null;if(d.hasOwnProperty(e)){var q;e=a.get(e+"Directive");for(var m=0,s=e.length;m<s;m++)try{q=e[m],(g===u||g>q.priority)&&-1!=q.restrict.indexOf(f)&&(h&&(q=Ob(q,{$$start:h,$$end:k})),b.push(q),l=q)}catch(I){c(I)}}return l}function D(b){if(d.hasOwnProperty(b))for(var c=a.get(b+"Directive"),e=0,f=c.length;e<f;e++)if(b=c[e],b.multiElement)return!0;
+return!1}function S(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;r(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});r(b,function(b,f){"class"==f?(E(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function of(a,b,c,d,e,f,g,l){var h=[],k,q,p=b[0],m=a.shift(),t=Ob(m,{templateUrl:null,transclude:null,
+replace:null,$$originalDirective:m}),I=z(m.templateUrl)?m.templateUrl(b,c):m.templateUrl,M=m.templateNamespace;b.empty();s(I).then(function(s){var F,v;s=Sc(s);if(m.replace){s=Sb.test(s)?Tc(Xb(M,N(s))):[];F=s[0];if(1!=s.length||F.nodeType!==qa)throw ma("tplrt",m.name,I);s={$attr:{}};T(d,b,F);var C=X(F,[],s);L(m.scope)&&y(C);a=C.concat(a);S(c,s)}else F=p,b.html(s);a.unshift(t);k=fa(a,F,c,e,b,m,f,g,l);r(d,function(a,c){a==F&&(d[c]=b[0])});for(q=O(b[0].childNodes,e);h.length;){s=h.shift();v=h.shift();
+var G=h.shift(),P=h.shift(),C=b[0];if(!s.$$destroyed){if(v!==p){var $=v.className;l.hasElementTranscludeDirective&&m.replace||(C=Ub(F));T(G,B(v),C);E(B(C),$)}v=k.transcludeOnThisElement?Q(s,k.transclude,P):P;k(q,s,C,d,v)}}h=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(h?h.push(b,c,d,a):(k.transcludeOnThisElement&&(a=Q(b,k.transclude,e)),k(q,b,c,d,a)))}}function da(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function Oa(a,b,c,d){if(b)throw ma("multidir",
+b.name,c.name,a,xa(d));}function za(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&G.$$addBindingClass(a);return function(a,c){var e=c.parent();b||G.$$addBindingClass(e);G.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Xb(a,b){a=K(a||"html");switch(a){case "svg":case "math":var c=W.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"==
+b)return $.HTML;var c=wa(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return $.RESOURCE_URL}function Pa(a,c,d,e,f){var h=R(a,e);f=g[e]||f;var k=b(d,!0,h,f);if(k){if("multiple"===e&&"select"===wa(a))throw ma("selmulti",xa(a));c.push({priority:100,compile:function(){return{pre:function(a,c,g){c=g.$$observers||(g.$$observers={});if(l.test(e))throw ma("nodomevents");var p=g[e];p!==d&&(k=p&&b(p,!0,h,f),d=p);k&&(g[e]=k(a),(c[e]||(c[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope||
+a).$watch(k,function(a,b){"class"===e&&a!=b?g.$updateClass(a,b):g.$set(e,a)}))}}}})}}function T(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,l;if(a)for(g=0,l=a.length;g<l;g++)if(a[g]==d){a[g++]=c;l=g+e-1;for(var h=a.length;g<h;g++,l++)l<h?a[g]=a[l]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=W.createDocumentFragment();a.appendChild(d);B(c).data(B(d).data());ta?(Qb=!0,ta.cleanData([d])):delete B.cache[d[B.expando]];d=1;for(e=b.length;d<e;d++)f=b[d],B(f).remove(),
+a.appendChild(f),delete b[d];b[0]=c;b.length=1}function Y(a,b){return w(function(){return a.apply(null,arguments)},a,b)}function Z(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(l){c(l,xa(d))}}var Yb=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a};Yb.prototype={$normalize:ya,$addClass:function(a){a&&0<a.length&&I.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&I.removeClass(this.$$element,a)},$updateClass:function(a,
+b){var c=Uc(a,b);c&&c.length&&I.addClass(this.$$element,c);(c=Uc(b,a))&&c.length&&I.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Mc(f,a),l=kf(f,a),f=a;g?(this.$$element.prop(a,b),e=g):l&&(this[l]=b,f=l);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=uc(a,"-"));g=wa(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=M(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",l=N(b),h=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,h=/\s/.test(l)?
+h:/(,)/,l=l.split(h),h=Math.floor(l.length/2),k=0;k<h;k++)var q=2*k,g=g+M(N(l[q]),!0),g=g+(" "+N(l[q+1]));l=N(l[2*k]).split(/\s/);g+=M(N(l[0]),!0);2===l.length&&(g+=" "+N(l[1]));this[a]=b=g}!1!==d&&(null===b||b===u?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&r(a[f],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ja()),e=d[a]||(d[a]=[]);e.push(b);m.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])});
+return function(){Ya(e,b)}}};var V=b.startSymbol(),na=b.endSymbol(),Sc="{{"==V||"}}"==na?ra:function(a){return a.replace(/\{\{/g,V).replace(/}}/g,na)},U=/^ngAttr[A-Z]/;G.$$addBindingInfo=k?function(a,b){var c=a.data("$binding")||[];H(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:A;G.$$addBindingClass=k?function(a){E(a,"ng-binding")}:A;G.$$addScopeInfo=k?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:A;G.$$addScopeClass=k?function(a,b){E(a,b?"ng-isolate-scope":
+"ng-scope")}:A;return G}]}function ya(b){return fb(b.replace(Rc,""))}function Uc(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function Tc(b){b=B(b);var a=b.length;if(1>=a)return b;for(;a--;)8===b[a].nodeType&&qf.call(b,a,1);return b}function Fe(){var b={},a=!1,c=/^(\S+)(\s+as\s+(\w+))?$/;this.register=function(a,c){Ma(a,"controller");L(a)?w(b,a):b[a]=c};this.allowGlobals=function(){a=
+!0};this.$get=["$injector","$window",function(d,e){function f(a,b,c,d){if(!a||!L(a.$scope))throw S("$controller")("noscp",d,b);a.$scope[b]=c}return function(g,h,l,k){var n,p,q;l=!0===l;k&&x(k)&&(q=k);if(x(g)){k=g.match(c);if(!k)throw rf("ctrlfmt",g);p=k[1];q=q||k[3];g=b.hasOwnProperty(p)?b[p]:wc(h.$scope,p,!0)||(a?wc(e,p,!0):u);La(g,p,!0)}if(l)return l=(H(g)?g[g.length-1]:g).prototype,n=Object.create(l||null),q&&f(h,q,n,p||g.name),w(function(){d.invoke(g,n,h,p);return n},{instance:n,identifier:q});
+n=d.instantiate(g,h,p);q&&f(h,q,n,p||g.name);return n}}]}function Ge(){this.$get=["$window",function(b){return B(b.document)}]}function He(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b,a){if(x(b)){var c=b.replace(sf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(Vc))||(d=(d=c.match(tf))&&uf[d[0]].test(c));d&&(b=pc(c))}}return b}function Wc(b){var a=ja(),c,d,e;if(!b)return a;r(b.split("\n"),function(b){e=b.indexOf(":");c=K(N(b.substr(0,
+e)));d=N(b.substr(e+1));c&&(a[c]=a[c]?a[c]+", "+d:d)});return a}function Xc(b){var a=L(b)?b:u;return function(c){a||(a=Wc(b));return c?(c=a[K(c)],void 0===c&&(c=null),c):a}}function Yc(b,a,c,d){if(z(d))return d(b,a,c);r(d,function(d){b=d(b,a,c)});return b}function Ke(){var b=this.defaults={transformResponse:[Zb],transformRequest:[function(a){return L(a)&&"[object File]"!==Ca.call(a)&&"[object Blob]"!==Ca.call(a)&&"[object FormData]"!==Ca.call(a)?ab(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},
+post:sa($b),put:sa($b),patch:sa($b)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},a=!1;this.useApplyAsync=function(b){return y(b)?(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=w({},a);b.data=a.data?Yc(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a){var b,c={};r(a,function(a,d){z(a)?(b=
+a(),null!=b&&(c[d]=b)):c[d]=a});return c}if(!ca.isObject(a))throw S("$http")("badreq",a);var e=w({method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse},a);e.headers=function(a){var c=b.headers,e=w({},a.headers),f,g,c=w({},c.common,c[K(a.method)]);a:for(f in c){a=K(f);for(g in e)if(K(g)===a)continue a;e[f]=c[f]}return d(e)}(a);e.method=vb(e.method);var f=[function(a){var d=a.headers,e=Yc(a.data,Xc(d),u,a.transformRequest);D(e)&&r(d,function(a,b){"content-type"===K(b)&&
+delete d[b]});D(a.withCredentials)&&!D(b.withCredentials)&&(a.withCredentials=b.withCredentials);return n(a,e).then(c,c)},u],g=h.when(e);for(r(t,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var l=f.shift(),g=g.then(a,l)}g.success=function(a){La(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){La(a,"fn");g.then(null,function(b){a(b.data,
+b.status,b.headers,e)});return g};return g}function n(c,f){function l(b,c,d,e){function f(){m(c,b,d,e)}E&&(200<=b&&300>b?E.put(Q,[b,c,Wc(d),e]):E.remove(Q));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function m(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:Xc(d),config:c,statusText:e})}function n(a){m(a.data,a.status,sa(a.headers()),a.statusText)}function t(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),M=I.promise,
+E,G,O=c.headers,Q=p(c.url,c.params);k.pendingRequests.push(c);M.then(t,t);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(E=L(c.cache)?c.cache:L(b.cache)?b.cache:q);E&&(G=E.get(Q),y(G)?G&&z(G.then)?G.then(n,n):H(G)?m(G[1],G[0],sa(G[2]),G[3]):m(G,200,{},"OK"):E.put(Q,M));D(G)&&((G=Zc(c.url)?e.cookies()[c.xsrfCookieName||b.xsrfCookieName]:u)&&(O[c.xsrfHeaderName||b.xsrfHeaderName]=G),d(c.method,Q,f,l,O,c.timeout,c.withCredentials,c.responseType));return M}function p(a,b){if(!b)return a;
+var c=[];Ed(b,function(a,b){null===a||D(a)||(H(a)||(a=[a]),r(a,function(a){L(a)&&(a=ha(a)?a.toISOString():ab(a));c.push(Ea(b)+"="+Ea(a))}))});0<c.length&&(a+=(-1==a.indexOf("?")?"?":"&")+c.join("&"));return a}var q=f("$http"),t=[];r(c,function(a){t.unshift(x(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){r(arguments,function(a){k[a]=function(b,c){return k(w(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){r(arguments,function(a){k[a]=function(b,c,d){return k(w(d||
+{},{method:a,url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function vf(){return new R.XMLHttpRequest}function Le(){this.$get=["$browser","$window","$document",function(b,a,c){return wf(b,vf,b.defer,a.angular.callbacks,c[0])}]}function wf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),n=null;f.type="text/javascript";f.src=a;f.async=!0;n=function(a){f.removeEventListener("load",n,!1);f.removeEventListener("error",n,!1);e.body.removeChild(f);f=null;var g=-1,t="unknown";
+a&&("load"!==a.type||d[b].called||(a={type:"error"}),t=a.type,g="error"===a.type?404:200);c&&c(g,t)};f.addEventListener("load",n,!1);f.addEventListener("error",n,!1);e.body.appendChild(f);return n}return function(e,h,l,k,n,p,q,t){function s(){m&&m();C&&C.abort()}function F(a,d,e,f,g){I!==u&&c.cancel(I);m=C=null;a(d,e,f,g);b.$$completeOutstandingRequest(A)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==K(e)){var v="_"+(d.counter++).toString(36);d[v]=function(a){d[v].data=a;d[v].called=!0};
+var m=f(h.replace("JSON_CALLBACK","angular.callbacks."+v),v,function(a,b){F(k,a,d[v].data,"",b);d[v]=A})}else{var C=a();C.open(e,h,!0);r(n,function(a,b){y(a)&&C.setRequestHeader(b,a)});C.onload=function(){var a=C.statusText||"",b="response"in C?C.response:C.responseText,c=1223===C.status?204:C.status;0===c&&(c=b?200:"file"==Aa(h).protocol?404:0);F(k,c,b,C.getAllResponseHeaders(),a)};e=function(){F(k,-1,null,null,"")};C.onerror=e;C.onabort=e;q&&(C.withCredentials=!0);if(t)try{C.responseType=t}catch($){if("json"!==
+t)throw $;}C.send(l||null)}if(0<p)var I=c(s,p);else p&&z(p.then)&&p.then(s)}}function Ie(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(f,g,t,s){function F(c){return c.replace(k,b).replace(n,a)}function v(a){try{var b=a;a=t?e.getTrusted(t,b):e.valueOf(b);var c;if(s&&!y(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;
+case "number":a=""+a;break;default:a=ab(a)}c=a}return c}catch(g){c=ac("interr",f,g.toString()),d(c)}}s=!!s;for(var m,C,r=0,I=[],M=[],E=f.length,G=[],O=[];r<E;)if(-1!=(m=f.indexOf(b,r))&&-1!=(C=f.indexOf(a,m+h)))r!==m&&G.push(F(f.substring(r,m))),r=f.substring(m+h,C),I.push(r),M.push(c(r,v)),r=C+l,O.push(G.length),G.push("");else{r!==E&&G.push(F(f.substring(r)));break}if(t&&1<G.length)throw ac("noconcat",f);if(!g||I.length){var Q=function(a){for(var b=0,c=I.length;b<c;b++){if(s&&D(a[b]))return;G[O[b]]=
+a[b]}return G.join("")};return w(function(a){var b=0,c=I.length,e=Array(c);try{for(;b<c;b++)e[b]=M[b](a);return Q(e)}catch(g){a=ac("interr",f,g.toString()),d(a)}},{exp:f,expressions:I,$$watchDelegate:function(a,b,c){var d;return a.$watchGroup(M,function(c,e){var f=Q(c);z(b)&&b.call(this,f,c!==e?d:f,a);d=f},c)}})}}var h=b.length,l=a.length,k=new RegExp(b.replace(/./g,f),"g"),n=new RegExp(a.replace(/./g,f),"g");g.startSymbol=function(){return b};g.endSymbol=function(){return a};return g}]}function Je(){this.$get=
+["$rootScope","$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var n=a.setInterval,p=a.clearInterval,q=0,t=y(k)&&!k,s=(t?d:c).defer(),F=s.promise;l=y(l)?l:0;F.then(null,null,e);F.$$intervalId=n(function(){s.notify(q++);0<l&&q>=l&&(s.resolve(q),p(F.$$intervalId),delete f[F.$$intervalId]);t||b.$apply()},h);f[F.$$intervalId]=s;return F}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):
+!1};return e}]}function Rd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),
+DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=sb(b[a]);
+return b.join("/")}function $c(b,a){var c=Aa(b);a.$$protocol=c.protocol;a.$$host=c.hostname;a.$$port=aa(c.port)||xf[c.protocol]||null}function ad(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Aa(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=rc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ua(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ga(b){var a=b.indexOf("#");
+return-1==a?b:b.substr(0,a)}function Gb(b){return b.replace(/(#.+)|#$/,"$1")}function cc(b,a,c){this.$$html5=!0;c=c||"";$c(b,this);this.$$parse=function(b){var c=ua(a,b);if(!x(c))throw Hb("ipthprfx",b,a);ad(c,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var b=Pb(this.$$search),c=this.$$hash?"#"+sb(this.$$hash):"";this.$$url=bc(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=a+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),
+!0;var f,g;(f=ua(b,d))!==u?(g=f,g=(f=ua(c,f))!==u?a+(ua("/",f)||f):b+g):(f=ua(a,d))!==u?g=a+f:a==d+"/"&&(g=a);g&&this.$$parse(g);return!!g}}function dc(b,a,c){$c(b,this);this.$$parse=function(d){var e=ua(b,d)||ua(a,d),f;D(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",D(e)&&(b=d,this.replace())):(f=ua(c,e),D(f)&&(f=e));ad(f,this);d=this.$$path;var e=b,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(d=(f=g.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var a=
+Pb(this.$$search),e=this.$$hash?"#"+sb(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+e;this.$$absUrl=b+(this.$$url?c+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ga(b)==Ga(a)?(this.$$parse(a),!0):!1}}function bd(b,a,c){this.$$html5=!0;dc.apply(this,arguments);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ga(d)?f=d:(g=ua(a,d))?f=b+c+g:a===d+"/"&&(f=a);f&&this.$$parse(f);return!!f};this.$$compose=function(){var a=Pb(this.$$search),
+e=this.$$hash?"#"+sb(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+e;this.$$absUrl=b+c+this.$$url}}function Ib(b){return function(){return this[b]}}function cd(b,a){return function(c){if(D(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Me(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return y(a)?(b=a,this):b};this.html5Mode=function(b){return Xa(b)?(a.enabled=b,this):L(b)?(Xa(b.enabled)&&(a.enabled=b.enabled),Xa(b.requireBase)&&
+(a.requireBase=b.requireBase),Xa(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var p=d.url(),q;if(a.enabled){if(!n&&a.requireBase)throw Hb("nobase");q=p.substring(0,p.indexOf("/",
+p.indexOf("//")+2))+(n||"/");n=e.history?cc:bd}else q=Ga(p),n=dc;var t=q.substr(0,Ga(q).lastIndexOf("/")+1);k=new n(q,t,"#"+b);k.$$parseLinkUrl(p,p);k.$$state=d.state();var s=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=B(b.target);"a"!==wa(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var l=e.prop("href"),h=e.attr("href")||e.attr("xlink:href");L(l)&&"[object SVGAnimatedString]"===l.toString()&&(l=
+Aa(l.animVal).href);s.test(l)||!l||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(l,h)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Gb(k.absUrl())!=Gb(p)&&d.url(k.absUrl(),!0);var F=!0;d.onUrlChange(function(a,b){D(ua(t,a))?g.location.href=a:(c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,
+!1,e)):(F=!1,l(d,e)))}),c.$$phase||c.$digest())});c.$watch(function(){var a=Gb(d.url()),b=Gb(k.absUrl()),f=d.state(),g=k.$$replace,q=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(F||q)F=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(q&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function Ne(){var b=!0,a=this;this.debugEnabled=function(a){return y(a)?(b=
+a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||A;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];r(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),
+debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function va(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw ga("isecfld",a);return b}function dd(b,a){b+="";if(!x(b))throw ga("iseccst",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw ga("isecfn",a);if(b.window===b)throw ga("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw ga("isecdom",a);if(b===Object)throw ga("isecobj",
+a);}return b}function ec(b){return b.constant}function jb(b,a,c,d,e){oa(b,e);oa(a,e);c=c.split(".");for(var f,g=0;1<c.length;g++){f=va(c.shift(),e);var h=0===g&&a&&a[f]||b[f];h||(h={},b[f]=h);b=oa(h,e)}f=va(c.shift(),e);oa(b[f],e);return b[f]=d}function Qa(b){return"constructor"==b}function ed(b,a,c,d,e,f,g){va(b,f);va(a,f);va(c,f);va(d,f);va(e,f);var h=function(a){return oa(a,f)},l=g||Qa(b)?h:ra,k=g||Qa(a)?h:ra,n=g||Qa(c)?h:ra,p=g||Qa(d)?h:ra,q=g||Qa(e)?h:ra;return function(f,g){var h=g&&g.hasOwnProperty(b)?
+g:f;if(null==h)return h;h=l(h[b]);if(!a)return h;if(null==h)return u;h=k(h[a]);if(!c)return h;if(null==h)return u;h=n(h[c]);if(!d)return h;if(null==h)return u;h=p(h[d]);return e?null==h?u:h=q(h[e]):h}}function yf(b,a){return function(c,d){return b(c,d,oa,a)}}function zf(b,a,c){var d=a.expensiveChecks,e=d?Af:Bf,f=e[b];if(f)return f;var g=b.split("."),h=g.length;if(a.csp)f=6>h?ed(g[0],g[1],g[2],g[3],g[4],c,d):function(a,b){var e=0,f;do f=ed(g[e++],g[e++],g[e++],g[e++],g[e++],c,d)(a,b),b=u,a=f;while(e<
+h);return f};else{var l="";d&&(l+="s = eso(s, fe);\nl = eso(l, fe);\n");var k=d;r(g,function(a,b){va(a,c);var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+"."+a;if(d||Qa(a))e="eso("+e+", fe)",k=!0;l+="if(s == null) return undefined;\ns="+e+";\n"});l+="return s;";a=new Function("s","l","eso","fe",l);a.toString=ea(l);k&&(a=yf(a,c));f=a}f.sharedGetter=!0;f.assign=function(a,c,d){return jb(a,d,b,c,b)};return e[b]=f}function fc(b){return z(b.valueOf)?b.valueOf():Cf.call(b)}function Oe(){var b=ja(),
+a=ja();this.$get=["$filter","$sniffer",function(c,d){function e(a){var b=a;a.sharedGetter&&(b=function(b,c){return a(b,c)},b.literal=a.literal,b.constant=a.constant,b.assign=a.assign);return b}function f(a,b){for(var c=0,d=a.length;c<d;c++){var e=a[c];e.constant||(e.inputs?f(e.inputs,b):-1===b.indexOf(e)&&b.push(e))}return b}function g(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=fc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function h(a,b,c,d){var e=d.$$inputs||(d.$$inputs=f(d.inputs,
+[])),l;if(1===e.length){var h=g,e=e[0];return a.$watch(function(a){var b=e(a);g(b,h)||(l=d(a),h=b&&fc(b));return l},b,c)}for(var k=[],q=0,p=e.length;q<p;q++)k[q]=g;return a.$watch(function(a){for(var b=!1,c=0,f=e.length;c<f;c++){var h=e[c](a);if(b||(b=!g(h,k[c])))k[c]=h&&fc(h)}b&&(l=d(a));return l},b,c)}function l(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);y(a)&&d.$$postDigest(function(){y(f)&&e()})},c)}function k(a,b,c,d){function e(a){var b=
+!0;r(a,function(a){y(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function n(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){z(b)&&b.apply(this,arguments);e()},c)}function p(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==k&&c!==l?function(c,d){var e=a(c,d);return b(e,c,d)}:function(c,d){var e=a(c,d),f=b(e,c,d);return y(e)?f:e};a.$$watchDelegate&&a.$$watchDelegate!==
+h?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=h,c.inputs=[a]);return c}var q={csp:d.csp,expensiveChecks:!1},t={csp:d.csp,expensiveChecks:!0};return function(d,f,g){var m,r,u;switch(typeof d){case "string":u=d=d.trim();var I=g?a:b;m=I[u];m||(":"===d.charAt(0)&&":"===d.charAt(1)&&(r=!0,d=d.substring(2)),g=g?t:q,m=new gc(g),m=(new kb(m,c,g)).parse(d),m.constant?m.$$watchDelegate=n:r?(m=e(m),m.$$watchDelegate=m.literal?k:l):m.inputs&&(m.$$watchDelegate=h),I[u]=m);return p(m,f);
+case "function":return p(d,f);default:return p(A,f)}}}]}function Qe(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return fd(function(a){b.$evalAsync(a)},a)}]}function Re(){this.$get=["$browser","$exceptionHandler",function(b,a){return fd(function(a){b.defer(a)},a)}]}function fd(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&&
+c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=u;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status];try{z(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(l){d.reject(l),a(l)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=S("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending||
+[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(L(b)||z(b))d=b&&b.then;z(d)?(this.promise.$$state.status=
+-1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(z(b)?
+b(c):c)}catch(l){a(l)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return l(e,!1)}return d&&z(d.then)?d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},n=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},p=function t(a){if(!z(a))throw h("norslvr",a);if(!(this instanceof t))return new t(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};
+p.defer=function(){return new g};p.reject=function(a){var b=new g;b.reject(a);return b.promise};p.when=n;p.all=function(a){var b=new g,c=0,d=H(a)?[]:{};r(a,function(a,e){c++;n(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return p}function $e(){this.$get=["$window","$timeout",function(b,a){function c(){for(var a=0;a<n.length;a++){var b=n[a];b&&(n[a]=null,b())}k=n.length=0}function d(a){var b=
+n.length;k++;n.push(a);0===b&&(l=h(c));return function(){0<=b&&(b=n[b]=null,0===--k&&l&&(l(),l=null,n.length=0))}}var e=b.requestAnimationFrame||b.webkitRequestAnimationFrame,f=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,g=!!e,h=g?function(a){var b=e(a);return function(){f(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};d.supported=g;var l,k=0,n=[];return d}]}function Pe(){function b(a){function b(){this.$$watchers=this.$$nextSibling=
+this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$id=++rb;this.$$ChildScope=null}b.prototype=a;return b}var a=10,c=S("$rootScope"),d=null,e=null;this.digestTtl=function(b){arguments.length&&(a=b);return a};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(f,g,h,l){function k(a){a.currentScope.$$destroyed=!0}function n(){this.$id=++rb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=
+null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$isolateBindings=null}function p(a){if(v.$$phase)throw c("inprog",v.$$phase);v.$$phase=a}function q(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function t(){}function s(){for(;u.length;)try{u.shift()()}catch(a){g(a)}e=null}function F(){null===e&&(e=l.defer(function(){v.$apply(s)}))}n.prototype={constructor:n,$new:function(a,c){var d;c=c||this;a?
+(d=new n,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=b(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(a||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,c){var e=h(a);if(e.$$watchDelegate)return e.$$watchDelegate(this,b,c,e);var f=this.$$watchers,g={fn:b,last:t,get:e,exp:a,eq:!!c};d=null;z(b)||(g.fn=A);f||(f=this.$$watchers=[]);f.unshift(g);return function(){Ya(f,
+g);d=null}},$watchGroup:function(a,b){function c(){l=!1;h?(h=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,l=!1,h=!0;if(!a.length){var k=!0;g.$evalAsync(function(){k&&b(e,e,g)});return function(){k=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});r(a,function(a,b){var h=g.$watch(a,function(a,f){e[b]=a;d[b]=f;l||(l=!0,g.$evalAsync(c))});f.push(h)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=
+a;var b,d,g,l;if(!D(e)){if(L(e))if(Ta(e))for(f!==p&&(f=p,t=f.length=0,k++),a=e.length,t!==a&&(k++,f.length=t=a),b=0;b<a;b++)l=f[b],g=e[b],d=l!==l&&g!==g,d||l===g||(k++,f[b]=g);else{f!==n&&(f=n={},t=0,k++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],l=f[b],b in f?(d=l!==l&&g!==g,d||l===g||(k++,f[b]=g)):(t++,f[b]=g,k++));if(t>a)for(b in k++,f)e.hasOwnProperty(b)||(t--,delete f[b])}else f!==e&&(f=e,k++);return k}}c.$stateful=!0;var d=this,e,f,g,l=1<b.length,k=0,q=h(a,c),p=[],n={},m=!0,t=0;return this.$watch(q,
+function(){m?(m=!1,b(e,e,d)):b(e,g,d);if(l)if(L(e))if(Ta(e)){g=Array(e.length);for(var a=0;a<e.length;a++)g[a]=e[a]}else for(a in g={},e)sc.call(e,a)&&(g[a]=e[a]);else g=e})},$digest:function(){var b,f,h,k,q,n,r=a,F,P=[],u,y;p("$digest");l.$$checkUrlChange();this===v&&null!==e&&(l.defer.cancel(e),s());d=null;do{n=!1;for(F=this;m.length;){try{y=m.shift(),y.scope.$eval(y.expression,y.locals)}catch(w){g(w)}d=null}a:do{if(k=F.$$watchers)for(q=k.length;q--;)try{if(b=k[q])if((f=b.get(F))!==(h=b.last)&&
+!(b.eq?ia(f,h):"number"===typeof f&&"number"===typeof h&&isNaN(f)&&isNaN(h)))n=!0,d=b,b.last=b.eq?Da(f,null):f,b.fn(f,h===t?f:h,F),5>r&&(u=4-r,P[u]||(P[u]=[]),P[u].push({msg:z(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){n=!1;break a}}catch(D){g(D)}if(!(k=F.$$childHead||F!==this&&F.$$nextSibling))for(;F!==this&&!(k=F.$$nextSibling);)F=F.$parent}while(F=k);if((n||m.length)&&!r--)throw v.$$phase=null,c("infdig",a,P);}while(n||m.length);for(v.$$phase=null;C.length;)try{C.shift()()}catch(B){g(B)}},
+$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(this!==v){for(var b in this.$$listenerCount)q(this,this.$$listenerCount[b],b);a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=
+this.$applyAsync=A;this.$on=this.$watch=this.$watchGroup=function(){return A};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}}},$eval:function(a,b){return h(a)(this,b)},$evalAsync:function(a,b){v.$$phase||m.length||l.defer(function(){m.length&&v.$digest()});m.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){C.push(a)},$apply:function(a){try{return p("$apply"),this.$eval(a)}catch(b){g(b)}finally{v.$$phase=
+null;try{v.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&u.push(b);F()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,q(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,l={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){l.defaultPrevented=
+!0},defaultPrevented:!1},h=Za([l],arguments,1),k,q;do{d=e.$$listeners[a]||c;l.currentScope=e;k=0;for(q=d.length;k<q;k++)if(d[k])try{d[k].apply(null,h)}catch(p){g(p)}else d.splice(k,1),k--,q--;if(f)return l.currentScope=null,l;e=e.$parent}while(e);l.currentScope=null;return l},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var f=Za([e],arguments,1),l,h;c=d;){e.currentScope=
+c;d=c.$$listeners[a]||[];l=0;for(h=d.length;l<h;l++)if(d[l])try{d[l].apply(null,f)}catch(k){g(k)}else d.splice(l,1),l--,h--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var v=new n,m=v.$$asyncQueue=[],C=v.$$postDigestQueue=[],u=v.$$applyAsyncQueue=[];return v}]}function Sd(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=
+function(a){return y(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Aa(c).href;return""===f||f.match(e)?c:"unsafe:"+f}}}function Df(b){if("self"===b)return b;if(x(b)){if(-1<b.indexOf("***"))throw Ba("iwcard",b);b=gd(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(Va(b))return new RegExp("^"+b.source+"$");throw Ba("imatcher");}function hd(b){var a=[];y(b)&&r(b,function(b){a.push(Df(b))});
+return a}function Te(){this.SCE_CONTEXTS=pa;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=hd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&&(a=hd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?Zc(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};
+return b}var f=function(a){throw Ba("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[pa.HTML]=e(g);h[pa.CSS]=e(g);h[pa.URL]=e(g);h[pa.JS]=e(g);h[pa.RESOURCE_URL]=e(h[pa.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Ba("icontext",a,b);if(null===b||b===u||""===b)return b;if("string"!==typeof b)throw Ba("itype",a);return new c(b)},getTrusted:function(c,e){if(null===e||e===u||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof
+g)return e.$$unwrapTrustedValue();if(c===pa.RESOURCE_URL){var g=Aa(e.toString()),p,q,t=!1;p=0;for(q=b.length;p<q;p++)if(d(b[p],g)){t=!0;break}if(t)for(p=0,q=a.length;p<q;p++)if(d(a[p],g)){t=!1;break}if(t)return e;throw Ba("insecurl",e.toString());}if(c===pa.HTML)return f(e);throw Ba("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function Se(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&
+8>Ra)throw Ba("iequirks");var d=sa(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=ra);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;r(pa,function(a,b){var c=K(b);d[fb("parse_as_"+c)]=function(b){return e(a,b)};d[fb("get_trusted_"+c)]=function(b){return f(a,b)};d[fb("trust_as_"+
+c)]=function(b){return g(a,b)}});return d}]}function Ue(){this.$get=["$window","$document",function(b,a){var c={},d=aa((/android (\d+)/.exec(K((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var p in l)if(k=h.exec(p)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);n=!!("animation"in l||g+"Animation"in
+l);!d||k&&n||(k=x(f.body.style.webkitTransition),n=x(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=Ra)return!1;if(D(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:db(),vendorPrefix:g,transitions:k,animations:n,android:d}}]}function We(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,g){e.totalPendingRequests++;x(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var h=
+a.defaults&&a.defaults.transformResponse;H(h)?h=h.filter(function(a){return a!==Zb}):h===Zb&&(h=null);return a.get(f,{cache:b,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(a){return a.data},function(a){if(!g)throw ma("tpload",f);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function Xe(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];r(a,function(a){var d=
+ca.element(a).data("$binding");d&&r(d,function(d){c?(new RegExp("(^|\\s)"+gd(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function Ye(){this.$get=
+["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){var n=y(k)&&!k,p=(n?d:c).defer(),q=p.promise;l=a.defer(function(){try{p.resolve(f())}catch(a){p.reject(a),e(a)}finally{delete g[q.$$timeoutId]}n||b.$apply()},l);q.$$timeoutId=l;g[l]=p;return q}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Aa(b){Ra&&(Z.setAttribute("href",b),b=Z.href);
+Z.setAttribute("href",b);return{href:Z.href,protocol:Z.protocol?Z.protocol.replace(/:$/,""):"",host:Z.host,search:Z.search?Z.search.replace(/^\?/,""):"",hash:Z.hash?Z.hash.replace(/^#/,""):"",hostname:Z.hostname,port:Z.port,pathname:"/"===Z.pathname.charAt(0)?Z.pathname:"/"+Z.pathname}}function Zc(b){b=x(b)?Aa(b):b;return b.protocol===id.protocol&&b.host===id.host}function Ze(){this.$get=ea(R)}function Ec(b){function a(c,d){if(L(c)){var e={};r(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+
+"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",jd);a("date",kd);a("filter",Ef);a("json",Ff);a("limitTo",Gf);a("lowercase",Hf);a("number",ld);a("orderBy",md);a("uppercase",If)}function Ef(){return function(b,a,c){if(!H(b))return b;var d;switch(null!==a?typeof a:"null"){case "function":break;case "boolean":case "null":case "number":case "string":d=!0;case "object":a=Jf(a,c,d);break;default:return b}return b.filter(a)}}function Jf(b,
+a,c){var d=L(b)&&"$"in b;!0===a?a=ia:z(a)||(a=function(a,b){if(D(a))return!1;if(null===a||null===b)return a===b;if(L(a)||L(b))return!1;a=K(""+a);b=K(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!L(e)?Ha(e,b.$,a,!1):Ha(e,b,a,c)}}function Ha(b,a,c,d,e){var f=null!==b?typeof b:"null",g=null!==a?typeof a:"null";if("string"===g&&"!"===a.charAt(0))return!Ha(b,a.substring(1),c,d);if(H(b))return b.some(function(b){return Ha(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==
+h.charAt(0)&&Ha(b[h],a,c,!0))return!0;return e?!1:Ha(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!z(e)&&!D(e)&&(f="$"===h,!Ha(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function jd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){D(d)&&(d=a.CURRENCY_SYM);D(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:nd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function ld(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==
+b?b:nd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function nd(b,a,c,d,e){if(!isFinite(b)||L(b))return"";var f=0>b;b=Math.abs(b);var g=b+"",h="",l=[],k=!1;if(-1!==g.indexOf("e")){var n=g.match(/([\d\.]+)e(-?)(\d+)/);n&&"-"==n[2]&&n[3]>e+1?b=0:(h=g,k=!0)}if(k)0<e&&1>b&&(h=b.toFixed(e),b=parseFloat(h));else{g=(g.split(od)[1]||"").length;D(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(od),k=g[0],g=g[1]||"",p=0,q=a.lgSize,
+t=a.gSize;if(k.length>=q+t)for(p=k.length-q,n=0;n<p;n++)0===(p-n)%t&&0!==n&&(h+=c),h+=k.charAt(n);for(n=p;n<k.length;n++)0===(k.length-n)%q&&0!==n&&(h+=c),h+=k.charAt(n);for(;g.length<e;)g+="0";e&&"0"!==e&&(h+=d+g.substr(0,e))}0===b&&(f=!1);l.push(f?a.negPre:a.posPre,h,f?a.negSuf:a.posSuf);return l.join("")}function Jb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function U(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=
+c;0===e&&-12==c&&(e=12);return Jb(e,a,d)}}function Kb(b,a){return function(c,d){var e=c["get"+b](),f=vb(a?"SHORT"+b:b);return d[f][e]}}function pd(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function qd(b){return function(a){var c=pd(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Jb(a,b)}}function hc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function kd(b){function a(a){var b;if(b=a.match(c)){a=
+new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=aa(b[9]+b[10]),g=aa(b[9]+b[11]));h.call(a,aa(b[1]),aa(b[2])-1,aa(b[3]));f=aa(b[4]||0)-f;g=aa(b[5]||0)-g;h=aa(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;x(c)&&(c=Kf.test(c)?
+aa(c):a(c));Y(c)&&(c=new Date(c));if(!ha(c))return c;for(;e;)(k=Lf.exec(e))?(h=Za(h,k,1),e=h.pop()):(h.push(e),e=null);f&&"UTC"===f&&(c=new Date(c.getTime()),c.setMinutes(c.getMinutes()+c.getTimezoneOffset()));r(h,function(a){l=Mf[a];g+=l?l(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Ff(){return function(b,a){D(a)&&(a=2);return ab(b,a)}}function Gf(){return function(b,a){Y(b)&&(b=b.toString());return H(b)||x(b)?(a=Infinity===Math.abs(Number(a))?Number(a):
+aa(a))?0<a?b.slice(0,a):b.slice(a):x(b)?"":[]:b}}function md(b){return function(a,c,d){function e(a,b){return b?function(b,c){return a(c,b)}:a}function f(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}function g(a){return null===a?"null":"function"===typeof a.valueOf&&(a=a.valueOf(),f(a))||"function"===typeof a.toString&&(a=a.toString(),f(a))?a:""}function h(a,b){var c=typeof a,d=typeof b;c===d&&"object"===c&&(a=g(a),b=g(b));return c===d?("string"===c&&(a=
+a.toLowerCase(),b=b.toLowerCase()),a===b?0:a<b?-1:1):c<d?-1:1}if(!Ta(a))return a;c=H(c)?c:[c];0===c.length&&(c=["+"]);c=c.map(function(a){var c=!1,d=a||ra;if(x(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))c="-"==a.charAt(0),a=a.substring(1);if(""===a)return e(h,c);d=b(a);if(d.constant){var f=d();return e(function(a,b){return h(a[f],b[f])},c)}}return e(function(a,b){return h(d(a),d(b))},c)});return $a.call(a).sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(0!==e)return e}return 0},
+d))}}function Ia(b){z(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ea(b)}function rd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Lb;f.$error={};f.$$success={};f.$pending=u;f.$name=e(a.name||a.ngForm||"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){r(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){r(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ma(a.$name,
+"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];r(f.$pending,function(b,c){f.$setValidity(c,null,a)});r(f.$error,function(b,c){f.$setValidity(c,null,a)});r(f.$$success,function(b,c){f.$setValidity(c,null,a)});Ya(g,a)};sd({ctrl:this,$element:b,set:function(a,b,c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];
+d&&(Ya(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Sa);d.addClass(b,Mb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Sa,Mb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;r(g,function(a){a.$setPristine()})};f.$setUntouched=function(){r(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b,"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function ic(b){b.$formatters.push(function(a){return b.$isEmpty(a)?
+a:a.toString()})}function lb(b,a,c,d,e,f){var g=K(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e=a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=N(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}};if(e.hasEvent("input"))a.on("input",l);else{var k,n=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};
+a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Nb(b,a){return function(c,d){var e,f;if(ha(c))return c;if(x(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(Nf.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,
+dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},r(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function mb(b,a,c,d){return function(e,f,g,h,l,k,n){function p(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function q(a){return y(a)?ha(a)?a:c(a):u}td(e,f,g,h);lb(e,f,g,h,l,k);var t=h&&h.$options&&h.$options.timezone,s;h.$$parserName=b;
+h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,s),"UTC"===t&&b.setMinutes(b.getMinutes()-b.getTimezoneOffset()),b):u});h.$formatters.push(function(a){if(a&&!ha(a))throw nb("datefmt",a);if(p(a)){if((s=a)&&"UTC"===t){var b=6E4*s.getTimezoneOffset();s=new Date(s.getTime()+b)}return n("date")(a,d,t)}s=null;return""});if(y(g.min)||g.ngMin){var r;h.$validators.min=function(a){return!p(a)||D(r)||c(a)>=r};g.$observe("min",function(a){r=q(a);h.$validate()})}if(y(g.max)||g.ngMax){var v;
+h.$validators.max=function(a){return!p(a)||D(v)||c(a)<=v};g.$observe("max",function(a){v=q(a);h.$validate()})}}}function td(b,a,c,d){(d.$$hasNativeValidators=L(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?u:b})}function ud(b,a,c,d,e){if(y(d)){b=b(d);if(!b.constant)throw nb("constexpr",c,d);return b(a)}return e}function jc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],
+n=0;n<b.length;n++)if(e==b[n])continue a;c.push(e)}return c}function e(a){if(!H(a)){if(x(a))return a.split(" ");if(L(a)){var b=[];r(a,function(a,c){a&&(b=b.concat(c.split(" ")))});return b}}return a}return{restrict:"AC",link:function(f,g,h){function l(a,b){var c=g.data("$classCounts")||{},d=[];r(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!n){var t=l(k,1);h.$addClass(t)}else if(!ia(b,
+n)){var s=e(n),t=d(k,s),k=d(s,k),t=l(t,1),k=l(k,-1);t&&t.length&&c.addClass(g,t);k&&k.length&&c.removeClass(g,k)}}n=sa(b)}var n;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function sd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function c(b,c){b=b?"-"+uc(b,"-"):"";
+a(ob+b,!0===c);a(vd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[vd]=!(f[ob]=e.hasClass(ob));d.$setValidity=function(b,e,f){e===u?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&&h(d.$pending,b,f),wd(d.$pending)&&(d.$pending=u));Xa(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(xd,!0),d.$valid=d.$invalid=u,c("",null)):(a(xd,!1),d.$valid=wd(d.$error),d.$invalid=
+!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?u:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function wd(b){if(b)for(var a in b)return!1;return!0}var Of=/^\/(.+)\/([a-z]*)$/,K=function(b){return x(b)?b.toLowerCase():b},sc=Object.prototype.hasOwnProperty,vb=function(b){return x(b)?b.toUpperCase():b},Ra,B,ta,$a=[].slice,qf=[].splice,Pf=[].push,Ca=Object.prototype.toString,Ja=S("ng"),ca=R.angular||(R.angular={}),eb,rb=0;Ra=W.documentMode;A.$inject=[];ra.$inject=[];var H=
+Array.isArray,N=function(b){return x(b)?b.trim():b},gd=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},db=function(){if(y(db.isActive_))return db.isActive_;var b=!(!W.querySelector("[ng-csp]")&&!W.querySelector("[data-ng-csp]"));if(!b)try{new Function("")}catch(a){b=!0}return db.isActive_=b},tb=["ng-","data-ng-","ng:","x-ng-"],Md=/[A-Z]/g,vc=!1,Qb,qa=1,bb=3,Qd={full:"1.3.20",major:1,minor:3,dot:20,codeName:"shallow-translucence"};T.expando="ng339";var Ab=
+T.cache={},hf=1;T._data=function(b){return this.cache[b[this.expando]]||{}};var cf=/([\:\-\_]+(.))/g,df=/^moz([A-Z])/,Qf={mouseleave:"mouseout",mouseenter:"mouseover"},Tb=S("jqLite"),gf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Sb=/<|&#?\w+;/,ef=/<([\w:]+)/,ff=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ka={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],
+td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ka.optgroup=ka.option;ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead;ka.th=ka.td;var Ka=T.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===W.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),T(R).on("load",a))},toString:function(){var b=[];r(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?B(this[b]):B(this[this.length+b])},length:0,push:Pf,sort:[].sort,
+splice:[].splice},Fb={};r("multiple selected checked disabled readOnly required open".split(" "),function(b){Fb[K(b)]=b});var Nc={};r("input select option textarea button form details".split(" "),function(b){Nc[b]=!0});var Oc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};r({data:Vb,removeData:yb},function(b,a){T[a]=b});r({data:Vb,inheritedData:Eb,scope:function(b){return B.data(b,"$scope")||Eb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return B.data(b,
+"$isolateScope")||B.data(b,"$isolateScopeNoTemplate")},controller:Jc,injector:function(b){return Eb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Bb,css:function(b,a,c){a=fb(a);if(y(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==bb&&2!==d&&8!==d)if(d=K(a),Fb[d])if(y(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||A).specified?d:u;else if(y(c))b.setAttribute(a,c);else if(b.getAttribute)return b=
+b.getAttribute(a,2),null===b?u:b},prop:function(b,a,c){if(y(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(D(b)){var d=a.nodeType;return d===qa||d===bb?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(D(a)){if(b.multiple&&"select"===wa(b)){var c=[];r(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(D(a))return b.innerHTML;xb(b,!0);b.innerHTML=a},empty:Kc},function(b,a){T.prototype[a]=
+function(a,d){var e,f,g=this.length;if(b!==Kc&&(2==b.length&&b!==Bb&&b!==Jc?a:d)===u){if(L(a)){for(e=0;e<g;e++)if(b===Vb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===u?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}});r({removeData:yb,on:function a(c,d,e,f){if(y(f))throw Tb("onargs");if(Fc(c)){var g=zb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=lf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],
+l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"===d?a(c,Qf[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Ic,one:function(a,c,d){a=B(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c,d)},replaceWith:function(a,c){var d,e=a.parentNode;xb(a);r(new T(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];r(a.childNodes,
+function(a){a.nodeType===qa&&c.push(a)});return c},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===qa||11===d){c=new T(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===qa){var d=a.firstChild;r(new T(c),function(c){a.insertBefore(c,d)})}},wrap:function(a,c){c=B(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Lc,detach:function(a){Lc(a,!0)},after:function(a,
+c){var d=a,e=a.parentNode;c=new T(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h,d.nextSibling);d=h}},addClass:Db,removeClass:Cb,toggleClass:function(a,c,d){c&&r(c.split(" "),function(c){var f=d;D(f)&&(f=!Bb(a,c));(f?Db:Cb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Ub,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=
+zb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:A,type:g,target:a},c.type&&(e=w(e,c)),c=sa(h),f=d?[e].concat(d):[e],r(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){T.prototype[c]=function(c,
+e,f){for(var g,h=0,l=this.length;h<l;h++)D(g)?(g=a(this[h],c,e,f),y(g)&&(g=B(g))):Hc(g,a(this[h],c,e,f));return y(g)?g:this};T.prototype.bind=T.prototype.on;T.prototype.unbind=T.prototype.off});gb.prototype={put:function(a,c){this[Na(a,this.nextUid)]=c},get:function(a){return this[Na(a,this.nextUid)]},remove:function(a){var c=this[a=Na(a,this.nextUid)];delete this[a];return c}};var Qc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,Rf=/,/,Sf=/^\s*(_?)(\S+?)\1\s*$/,Pc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Fa=S("$injector");
+cb.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e=[];if(a.length){if(c)throw x(d)&&d||(d=a.name||mf(a)),Fa("strictdi",d);c=a.toString().replace(Pc,"");c=c.match(Qc);r(c[1].split(Rf),function(a){a.replace(Sf,function(a,c,d){e.push(d)})})}a.$inject=e}}else H(a)?(c=a.length-1,La(a[c],"fn"),e=a.slice(0,c)):La(a,"fn",!0);return e};var Tf=S("$animate"),Ce=["$provide",function(a){this.$$selectors={};this.register=function(c,d){var e=c+"-animation";if(c&&"."!=c.charAt(0))throw Tf("notcsel",
+c);this.$$selectors[c.substr(1)]=e;a.factory(e,d)};this.classNameFilter=function(a){1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null);return this.$$classNameFilter};this.$get=["$$q","$$asyncCallback","$rootScope",function(a,d,e){function f(d){var f,g=a.defer();g.promise.$$cancelFn=function(){f&&f()};e.$$postDigest(function(){f=d(function(){g.resolve()})});return g.promise}function g(a,c){var d=[],e=[],f=ja();r((a.attr("class")||"").split(/\s+/),function(a){f[a]=!0});r(c,function(a,
+c){var g=f[c];!1===a&&g?e.push(c):!0!==a||g||d.push(c)});return 0<d.length+e.length&&[d.length?d:null,e.length?e:null]}function h(a,c,d){for(var e=0,f=c.length;e<f;++e)a[c[e]]=d}function l(){n||(n=a.defer(),d(function(){n.resolve();n=null}));return n.promise}function k(a,c){if(ca.isObject(c)){var d=w(c.from||{},c.to||{});a.css(d)}}var n;return{animate:function(a,c,d){k(a,{from:c,to:d});return l()},enter:function(a,c,d,e){k(a,e);d?d.after(a):c.prepend(a);return l()},leave:function(a,c){k(a,c);a.remove();
+return l()},move:function(a,c,d,e){return this.enter(a,c,d,e)},addClass:function(a,c,d){return this.setClass(a,c,[],d)},$$addClassImmediately:function(a,c,d){a=B(a);c=x(c)?c:H(c)?c.join(" "):"";r(a,function(a){Db(a,c)});k(a,d);return l()},removeClass:function(a,c,d){return this.setClass(a,[],c,d)},$$removeClassImmediately:function(a,c,d){a=B(a);c=x(c)?c:H(c)?c.join(" "):"";r(a,function(a){Cb(a,c)});k(a,d);return l()},setClass:function(a,c,d,e){var k=this,l=!1;a=B(a);var m=a.data("$$animateClasses");
+m?e&&m.options&&(m.options=ca.extend(m.options||{},e)):(m={classes:{},options:e},l=!0);e=m.classes;c=H(c)?c:c.split(" ");d=H(d)?d:d.split(" ");h(e,c,!0);h(e,d,!1);l&&(m.promise=f(function(c){var d=a.data("$$animateClasses");a.removeData("$$animateClasses");if(d){var e=g(a,d.classes);e&&k.$$setClassImmediately(a,e[0],e[1],d.options)}c()}),a.data("$$animateClasses",m));return m.promise},$$setClassImmediately:function(a,c,d,e){c&&this.$$addClassImmediately(a,c);d&&this.$$removeClassImmediately(a,d);
+k(a,e);return l()},enabled:A,cancel:A}}]}],ma=S("$compile");xc.$inject=["$provide","$$sanitizeUriProvider"];var Rc=/^((?:x|data)[\:\-_])/i,rf=S("$controller"),Vc="application/json",$b={"Content-Type":Vc+";charset=utf-8"},tf=/^\[|^\{(?!\{)/,uf={"[":/]$/,"{":/}$/},sf=/^\)\]\}',?\n/,ac=S("$interpolate"),Uf=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,xf={http:80,https:443,ftp:21},Hb=S("$location"),Vf={$$html5:!1,$$replace:!1,absUrl:Ib("$$absUrl"),url:function(a){if(D(a))return this.$$url;var c=Uf.exec(a);(c[1]||
+""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Ib("$$protocol"),host:Ib("$$host"),port:Ib("$$port"),path:cd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(x(a)||Y(a))a=a.toString(),this.$$search=rc(a);else if(L(a))a=Da(a,{}),r(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Hb("isrcharg");
+break;default:D(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:cd("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};r([bd,dc,cc],function(a){a.prototype=Object.create(Vf);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==cc||!this.$$html5)throw Hb("nostate");this.$$state=D(c)?null:c;return this}});var ga=S("$parse"),Wf=Function.prototype.call,Xf=Function.prototype.apply,
+Yf=Function.prototype.bind,pb=ja();r({"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:function(){}},function(a,c){a.constant=a.literal=a.sharedGetter=!0;pb[c]=a});pb["this"]=function(a){return a};pb["this"].sharedGetter=!0;var qb=w(ja(),{"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return y(d)?y(e)?d+e:d:y(e)?e:u},"-":function(a,c,d,e){d=d(a,c);e=e(a,c);return(y(d)?d:0)-(y(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,
+c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"===":function(a,c,d,e){return d(a,c)===e(a,c)},"!==":function(a,c,d,e){return d(a,c)!==e(a,c)},"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,
+c)||e(a,c)},"!":function(a,c,d){return!d(a,c)},"=":!0,"|":!0}),Zf={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,
+text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var c=a+this.peek(),d=c+this.peek(2),e=qb[c],f=qb[d];qb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===
+typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=y(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw ga("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=K(this.text.charAt(this.index));
+if("."==d||this.isNumber(d))a+=d;else{var e=this.peek();if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&
+!this.isNumber(c))break;this.index++}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+=4,d+=String.fromCharCode(parseInt(f,16))):d+=Zf[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===
+a){this.index++;this.tokens.push({index:c,text:e,constant:!0,value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var kb=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d};kb.ZERO=w(function(){return 0},{sharedGetter:!0,constant:!0});kb.prototype={constructor:kb,parse:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.statements();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);a.literal=!!a.literal;a.constant=!!a.constant;
+return a},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.peek().identifier&&this.peek().text in pb?a=pb[this.consume().text]:this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var c,d;c=this.expect("(","[",".");)"("===c.text?(a=this.functionCall(a,d),d=null):"["===c.text?(d=a,a=this.objectIndex(a)):
+"."===c.text?(d=a,a=this.fieldAccess(a)):this.throwError("IMPOSSIBLE");return a},throwError:function(a,c){throw ga("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},peekToken:function(){if(0===this.tokens.length)throw ga("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,
+c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},consume:function(a){if(0===this.tokens.length)throw ga("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},unaryFn:function(a,c){var d=qb[a];return w(function(a,f){return d(a,f,c)},{constant:c.constant,inputs:[c]})},binaryFn:function(a,c,d,e){var f=qb[c];return w(function(c,e){return f(c,e,a,d)},{constant:a.constant&&d.constant,inputs:!e&&[a,d]})},identifier:function(){for(var a=
+this.consume().text;this.peek(".")&&this.peekAhead(1).identifier&&!this.peekAhead(2,"(");)a+=this.consume().text+this.consume().text;return zf(a,this.options,this.text)},constant:function(){var a=this.consume().value;return w(function(){return a},{constant:!0,literal:!0})},statements:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.filterChain()),!this.expect(";"))return 1===a.length?a[0]:function(c,d){for(var e,f=0,g=a.length;f<g;f++)e=a[f](c,d);return e}},
+filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},filter:function(a){var c=this.$filter(this.consume().text),d,e;if(this.peek(":"))for(d=[],e=[];this.expect(":");)d.push(this.expression());var f=[a].concat(d||[]);return w(function(f,h){var l=a(f,h);if(e){e[0]=l;for(l=d.length;l--;)e[l+1]=d[l](f,h);return c.apply(u,e)}return c(l)},{constant:!c.$stateful&&f.every(ec),inputs:!c.$stateful&&f})},expression:function(){return this.assignment()},assignment:function(){var a=
+this.ternary(),c,d;return(d=this.expect("="))?(a.assign||this.throwError("implies assignment but ["+this.text.substring(0,d.index)+"] can not be assigned to",d),c=this.ternary(),w(function(d,f){return a.assign(d,c(d,f),f)},{inputs:[a,c]})):a},ternary:function(){var a=this.logicalOR(),c;if(this.expect("?")&&(c=this.assignment(),this.consume(":"))){var d=this.assignment();return w(function(e,f){return a(e,f)?c(e,f):d(e,f)},{constant:a.constant&&c.constant&&d.constant})}return a},logicalOR:function(){for(var a=
+this.logicalAND(),c;c=this.expect("||");)a=this.binaryFn(a,c.text,this.logicalAND(),!0);return a},logicalAND:function(){for(var a=this.equality(),c;c=this.expect("&&");)a=this.binaryFn(a,c.text,this.equality(),!0);return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a=this.binaryFn(a,c.text,this.relational());return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a=this.binaryFn(a,c.text,this.additive());return a},
+additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.text,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.text,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(kb.ZERO,a.text,this.unary()):(a=this.expect("!"))?this.unaryFn(a.text,this.unary()):this.primary()},fieldAccess:function(a){var c=this.identifier();
+return w(function(d,e,f){d=f||a(d,e);return null==d?u:c(d)},{assign:function(d,e,f){var g=a(d,f);g||a.assign(d,g={},f);return c.assign(g,e)}})},objectIndex:function(a){var c=this.text,d=this.expression();this.consume("]");return w(function(e,f){var g=a(e,f),h=dd(d(e,f),c);va(h,c);return g?oa(g[h],c):u},{assign:function(e,f,g){var h=va(dd(d(e,g),c),c),l=oa(a(e,g),c);l||a.assign(e,l={},g);return l[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());
+while(this.expect(","))}this.consume(")");var e=this.text,f=d.length?[]:null;return function(g,h){var l=c?c(g,h):y(c)?u:g,k=a(g,h,l)||A;if(f)for(var n=d.length;n--;)f[n]=oa(d[n](g,h),e);oa(l,e);if(k){if(k.constructor===k)throw ga("isecfn",e);if(k===Wf||k===Xf||k===Yf)throw ga("isecff",e);}l=k.apply?k.apply(l,f):k(f[0],f[1],f[2],f[3],f[4]);f&&(f.length=0);return oa(l,e)}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))
+}this.consume("]");return w(function(c,d){for(var e=[],f=0,g=a.length;f<g;f++)e.push(a[f](c,d));return e},{literal:!0,constant:a.every(ec),inputs:a})},object:function(){var a=[],c=[];if("}"!==this.peekToken().text){do{if(this.peek("}"))break;var d=this.consume();d.constant?a.push(d.value):d.identifier?a.push(d.text):this.throwError("invalid key",d);this.consume(":");c.push(this.expression())}while(this.expect(","))}this.consume("}");return w(function(d,f){for(var g={},h=0,l=c.length;h<l;h++)g[a[h]]=
+c[h](d,f);return g},{literal:!0,constant:c.every(ec),inputs:c})}};var Bf=ja(),Af=ja(),Cf=Object.prototype.valueOf,Ba=S("$sce"),pa={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ma=S("$compile"),Z=W.createElement("a"),id=Aa(R.location.href);Ec.$inject=["$provide"];jd.$inject=["$locale"];ld.$inject=["$locale"];var od=".",Mf={yyyy:U("FullYear",4),yy:U("FullYear",2,0,!0),y:U("FullYear",1),MMMM:Kb("Month"),MMM:Kb("Month",!0),MM:U("Month",2,1),M:U("Month",1,1),dd:U("Date",2),d:U("Date",
+1),HH:U("Hours",2),H:U("Hours",1),hh:U("Hours",2,-12),h:U("Hours",1,-12),mm:U("Minutes",2),m:U("Minutes",1),ss:U("Seconds",2),s:U("Seconds",1),sss:U("Milliseconds",3),EEEE:Kb("Day"),EEE:Kb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Jb(Math[0<a?"floor":"ceil"](a/60),2)+Jb(Math.abs(a%60),2))},ww:qd(2),w:qd(1),G:hc,GG:hc,GGG:hc,GGGG:function(a,c){return 0>=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},Lf=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
+Kf=/^\-?\d+$/;kd.$inject=["$locale"];var Hf=ea(K),If=ea(vb);md.$inject=["$parse"];var Td=ea({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===Ca.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),wb={};r(Fb,function(a,c){if("multiple"!=a){var d=ya("ng-"+c);wb[d]=function(){return{restrict:"A",priority:100,link:function(a,f,g){a.$watch(g[d],
+function(a){g.$set(c,!!a)})}}}}});r(Oc,function(a,c){wb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(Of))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});r(["src","srcset","href"],function(a){var c=ya("ng-"+a);wb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===Ca.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",
+g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ra&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Lb={$addControl:A,$$renameControl:function(a,c){a.$name=c},$removeControl:A,$setValidity:A,$setDirty:A,$setPristine:A,$setSubmitted:A};rd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var yd=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:rd,compile:function(d,e){d.addClass(Sa).addClass(ob);var f=e.name?"name":a&&e.ngForm?"ngForm":
+!1;return{pre:function(a,d,e,k){if(!("action"in e)){var n=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",n,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",n,!1)},0,!1)})}var p=k.$$parentForm;f&&(jb(a,null,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(jb(a,null,k.$name,u,k.$name),p.$$renameControl(k,c),jb(a,null,k.$name,k,k.$name))}));d.on("$destroy",function(){p.$removeControl(k);
+f&&jb(a,null,e[f],u,k.$name);w(k,Lb)})}}}}}]},Ud=yd(),ge=yd(!0),Nf=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,$f=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,ag=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,bg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,zd=/^(\d{4})-(\d{2})-(\d{2})$/,Ad=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,kc=/^(\d{4})-W(\d\d)$/,Bd=/^(\d{4})-(\d\d)$/,
+Cd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Dd={text:function(a,c,d,e,f,g){lb(a,c,d,e,f,g);ic(e)},date:mb("date",zd,Nb(zd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":mb("datetimelocal",Ad,Nb(Ad,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:mb("time",Cd,Nb(Cd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:mb("week",kc,function(a,c){if(ha(a))return a;if(x(a)){kc.lastIndex=0;var d=kc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=pd(e),f=7*(f-1);c&&(d=c.getHours(),g=
+c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:mb("month",Bd,Nb(Bd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){td(a,c,d,e);lb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:bg.test(a)?parseFloat(a):u});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!Y(a))throw nb("numfmt",a);a=a.toString()}return a});if(y(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||
+D(h)||a>=h};d.$observe("min",function(a){y(a)&&!Y(a)&&(a=parseFloat(a,10));h=Y(a)&&!isNaN(a)?a:u;e.$validate()})}if(y(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||D(l)||a<=l};d.$observe("max",function(a){y(a)&&!Y(a)&&(a=parseFloat(a,10));l=Y(a)&&!isNaN(a)?a:u;e.$validate()})}},url:function(a,c,d,e,f,g){lb(a,c,d,e,f,g);ic(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||$f.test(d)}},email:function(a,c,d,e,f,g){lb(a,c,d,e,f,g);ic(e);
+e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||ag.test(d)}},radio:function(a,c,d,e){D(d.name)&&c.attr("name",++rb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=ud(l,a,"ngTrueValue",d.ngTrueValue,!0),n=ud(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&
+a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ia(a,k)});e.$parsers.push(function(a){return a?k:n})},hidden:A,button:A,submit:A,reset:A,file:A},yc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Dd[K(h.type)]||Dd.text)(f,g,h,l[0],c,a,d,e)}}}}],cg=/^(true|false|\d+)$/,ye=function(){return{restrict:"A",priority:100,compile:function(a,
+c){return cg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},Zd=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===u?"":a})}}}}],ae=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));
+c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===u?"":a})}}}}],$d=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],xe=ea({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),
+be=jc("",!0),de=jc("Odd",0),ce=jc("Even",1),ee=Ia({compile:function(a,c){c.$set("ngCloak",u);a.removeClass("ng-cloak")}}),fe=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Dc={},dg={blur:!0,focus:!0};r("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ya("ng-"+a);Dc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=
+d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};dg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ie=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=W.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=
+ub(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],je=["$templateRequest","$anchorScroll","$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(e,f){var g=f.ngInclude||f.src,h=f.onload||"",l=f.autoscroll;return function(e,f,p,q,r){var s=0,u,v,m,C=function(){v&&(v.remove(),v=null);u&&(u.$destroy(),u=null);m&&(d.leave(m).then(function(){v=null}),v=m,m=null)};e.$watch(g,function(g){var p=function(){!y(l)||l&&!e.$eval(l)||
+c()},M=++s;g?(a(g,!0).then(function(a){if(M===s){var c=e.$new();q.template=a;a=r(c,function(a){C();d.enter(a,null,f).then(p)});u=c;m=a;u.$emit("$includeContentLoaded",g);e.$eval(h)}},function(){M===s&&(C(),e.$emit("$includeContentError",g))}),e.$emit("$includeContentRequested",g)):(C(),q.template=null)})}}}}],Ae=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Gc(f.template,W).childNodes)(c,function(a){d.append(a)},
+{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],ke=Ia({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),we=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?N(f):f;e.$parsers.push(function(a){if(!D(a)){var c=[];a&&r(a.split(h),function(a){a&&c.push(g?N(a):a)});return c}});e.$formatters.push(function(a){return H(a)?a.join(f):u});e.$isEmpty=function(a){return!a||
+!a.length}}}},ob="ng-valid",vd="ng-invalid",Sa="ng-pristine",Mb="ng-dirty",xd="ng-pending",nb=S("ngModel"),eg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=u;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;
+this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=u;this.$name=n(d.name||"",!1)(a);var p=f(d.ngModel),q=p.assign,t=p,s=q,F=null,v,m=this;this.$$setOptions=function(a){if((m.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");t=function(a){var d=p(a);z(d)&&(d=c(a));return d};s=function(a,c){z(p(a))?g(a,{$$$p:m.$modelValue}):q(a,m.$modelValue)}}else if(!p.assign)throw nb("nonassign",d.ngModel,xa(e));};this.$render=A;this.$isEmpty=function(a){return D(a)||
+""===a||null===a||a!==a};var C=e.inheritedData("$formController")||Lb,w=0;sd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:C,$animate:g});this.$setPristine=function(){m.$dirty=!1;m.$pristine=!0;g.removeClass(e,Mb);g.addClass(e,Sa)};this.$setDirty=function(){m.$dirty=!0;m.$pristine=!1;g.removeClass(e,Sa);g.addClass(e,Mb);C.$setDirty()};this.$setUntouched=function(){m.$touched=!1;m.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=
+function(){m.$touched=!0;m.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(F);m.$viewValue=m.$$lastCommittedViewValue;m.$render()};this.$validate=function(){if(!Y(m.$modelValue)||!isNaN(m.$modelValue)){var a=m.$$rawModelValue,c=m.$valid,d=m.$modelValue,e=m.$options&&m.$options.allowInvalid;m.$$runValidators(a,m.$$lastCommittedViewValue,function(f){e||c===f||(m.$modelValue=f?a:u,m.$modelValue!==d&&m.$$writeModelToScope())})}};this.$$runValidators=
+function(a,c,d){function e(){var d=!0;r(m.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(r(m.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;r(m.$asyncValidators,function(f,h){var l=f(a,c);if(!l||!z(l.then))throw nb("$asyncValidators",l);g(h,u);d.push(l.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},A):h(!0)}function g(a,c){l===w&&m.$setValidity(a,c)}function h(a){l===w&&d(a)}w++;var l=w;(function(){var a=
+m.$$parserName||"parse";if(v===u)g(a,null);else return v||(r(m.$validators,function(a,c){g(c,null)}),r(m.$asyncValidators,function(a,c){g(c,null)})),g(a,v),v;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=m.$viewValue;h.cancel(F);if(m.$$lastCommittedViewValue!==a||""===a&&m.$$hasNativeValidators)m.$$lastCommittedViewValue=a,m.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=m.$$lastCommittedViewValue;if(v=D(c)?u:!0)for(var d=
+0;d<m.$parsers.length;d++)if(c=m.$parsers[d](c),D(c)){v=!1;break}Y(m.$modelValue)&&isNaN(m.$modelValue)&&(m.$modelValue=t(a));var e=m.$modelValue,f=m.$options&&m.$options.allowInvalid;m.$$rawModelValue=c;f&&(m.$modelValue=c,m.$modelValue!==e&&m.$$writeModelToScope());m.$$runValidators(c,m.$$lastCommittedViewValue,function(a){f||(m.$modelValue=a?c:u,m.$modelValue!==e&&m.$$writeModelToScope())})};this.$$writeModelToScope=function(){s(a,m.$modelValue);r(m.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};
+this.$setViewValue=function(a,c){m.$viewValue=a;m.$options&&!m.$options.updateOnDefault||m.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=m.$options;e&&y(e.debounce)&&(e=e.debounce,Y(e)?d=e:Y(e[c])?d=e[c]:Y(e["default"])&&(d=e["default"]));h.cancel(F);d?F=h(function(){m.$commitViewValue()},d):l.$$phase?m.$commitViewValue():a.$apply(function(){m.$commitViewValue()})};a.$watch(function(){var c=t(a);if(c!==m.$modelValue&&(m.$modelValue===m.$modelValue||c===c)){m.$modelValue=
+m.$$rawModelValue=c;v=u;for(var d=m.$formatters,e=d.length,f=c;e--;)f=d[e](f);m.$viewValue!==f&&(m.$viewValue=m.$$lastCommittedViewValue=f,m.$render(),m.$$runValidators(c,f,A))}return c})}],ve=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:eg,priority:1,compile:function(c){c.addClass(Sa).addClass("ng-untouched").addClass(ob);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Lb;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name",
+function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy",function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],fg=/(\s+|^)default(\s+|$)/,ze=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=a.$eval(c.ngModelOptions);
+this.$options.updateOn!==u?(this.$options.updateOnDefault=!1,this.$options.updateOn=N(this.$options.updateOn.replace(fg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},le=Ia({terminal:!0,priority:1E3}),me=["$locale","$interpolate",function(a,c){var d=/{}/g,e=/^when(Minus)?(.+)$/;return{restrict:"EA",link:function(f,g,h){function l(a){g.text(a||"")}var k=h.count,n=h.$attr.when&&g.attr(h.$attr.when),p=h.offset||0,q=f.$eval(n)||{},t={},n=c.startSymbol(),s=
+c.endSymbol(),u=n+k+"-"+p+s,v=ca.noop,m;r(h,function(a,c){var d=e.exec(c);d&&(d=(d[1]?"-":"")+K(d[2]),q[d]=g.attr(h.$attr[c]))});r(q,function(a,e){t[e]=c(a.replace(d,u))});f.$watch(k,function(c){c=parseFloat(c);var d=isNaN(c);d||c in q||(c=a.pluralCat(c-p));c===m||d&&isNaN(m)||(v(),v=f.$watch(t[c],l),m=c)})}}}],ne=["$parse","$animate",function(a,c){var d=S("ngRepeat"),e=function(a,c,d,e,k,n,p){a[d]=e;k&&(a[k]=n);a.$index=c;a.$first=0===c;a.$last=c===p-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=
+0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=W.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var n=k[1],p=k[2],q=k[3],t=k[4],k=n.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!k)throw d("iidexp",n);var s=k[3]||k[1],F=k[2];if(q&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(q)||
+/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(q)))throw d("badident",q);var v,m,C,y,w={$id:Na};t?v=a(t):(C=function(a,c){return Na(c)},y=function(a){return a});return function(a,f,g,k,n){v&&(m=function(c,d,e){F&&(w[F]=c);w[s]=d;w.$index=e;return v(a,w)});var t=ja();a.$watchCollection(p,function(g){var k,p,v=f[0],G,w=ja(),D,I,A,z,H,O,x;q&&(a[q]=g);if(Ta(g))H=g,p=m||C;else{p=m||y;H=[];for(x in g)g.hasOwnProperty(x)&&"$"!=x.charAt(0)&&H.push(x);H.sort()}D=
+H.length;x=Array(D);for(k=0;k<D;k++)if(I=g===H?k:H[k],A=g[I],z=p(I,A,k),t[z])O=t[z],delete t[z],w[z]=O,x[k]=O;else{if(w[z])throw r(x,function(a){a&&a.scope&&(t[a.id]=a)}),d("dupes",h,z,A);x[k]={id:z,scope:u,clone:u};w[z]=!0}for(G in t){O=t[G];z=ub(O.clone);c.leave(z);if(z[0].parentNode)for(k=0,p=z.length;k<p;k++)z[k].$$NG_REMOVED=!0;O.scope.$destroy()}for(k=0;k<D;k++)if(I=g===H?k:H[k],A=g[I],O=x[k],O.scope){G=v;do G=G.nextSibling;while(G&&G.$$NG_REMOVED);O.clone[0]!=G&&c.move(ub(O.clone),null,B(v));
+v=O.clone[O.clone.length-1];e(O.scope,k,s,A,F,I,D)}else n(function(a,d){O.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a,null,B(v));v=f;O.clone=a;w[O.id]=O;e(O.scope,k,s,A,F,I,D)});t=w})}}}}],oe=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],he=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?
+"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],pe=Ia(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&r(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),qe=["$animate",function(a){return{restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],n=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch||e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=
+0;for(e=k.length;d<e;++d){var s=ub(h[d].clone);k[d].$destroy();(l[d]=a.leave(s)).then(n(l,d))}h.length=0;k.length=0;(g=f.cases["!"+c]||f.cases["?"])&&r(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=W.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],re=Ia({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,
+element:c})}}),se=Ia({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),ue=Ia({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw S("ngTransclude")("orphan",xa(c));f(function(a){c.empty();c.append(a)})}}),Vd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],gg=S("ngOptions"),te=ea({restrict:"A",
+terminal:!0}),Wd=["$compile","$parse",function(a,c){var d=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,e={$setViewValue:A};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope","$attrs",function(a,c,d){var l=this,k={},n=e,p;l.databound=d.ngModel;l.init=function(a,c,d){n=a;p=d};l.addOption=function(c,d){Ma(c,'"option value"');
+k[c]=!0;n.$viewValue==c&&(a.val(c),p.parent()&&p.remove());d&&d[0].hasAttribute("selected")&&(d[0].selected=!0)};l.removeOption=function(a){this.hasOption(a)&&(delete k[a],n.$viewValue===a&&this.renderUnknownOption(a))};l.renderUnknownOption=function(c){c="? "+Na(c)+" ?";p.val(c);a.prepend(p);a.val(c);p.prop("selected",!0)};l.hasOption=function(a){return k.hasOwnProperty(a)};c.$on("$destroy",function(){l.renderUnknownOption=A})}],link:function(e,g,h,l){function k(a,c,d,e){d.$render=function(){var a=
+d.$viewValue;e.hasOption(a)?(z.parent()&&z.remove(),c.val(a),""===a&&v.prop("selected",!0)):null==a&&v?c.val(""):e.renderUnknownOption(a)};c.on("change",function(){a.$apply(function(){z.parent()&&z.remove();d.$setViewValue(c.val())})})}function n(a,c,d){var e;d.$render=function(){var a=new gb(d.$viewValue);r(c.find("option"),function(c){c.selected=y(a.get(c.value))})};a.$watch(function(){ia(e,d.$viewValue)||(e=sa(d.$viewValue),d.$render())});c.on("change",function(){a.$apply(function(){var a=[];r(c.find("option"),
+function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function p(e,f,g){function h(a,c,d){T[A]=d;I&&(T[I]=c);return a(e,T)}function l(a){var c;if(t)if(K&&H(a)){c=new gb([]);for(var d=0;d<a.length;d++)c.put(h(K,null,a[d]),!0)}else c=new gb(a);else K&&(a=h(K,null,a));return function(d,e){var f;f=K?K:x?x:E;return t?y(c.remove(h(f,d,e))):a===h(f,d,e)}}function k(){m||(e.$$postDigest(p),m=!0)}function n(a,c,d){a[c]=a[c]||0;a[c]+=d?1:-1}function p(){m=!1;var a={"":[]},c=[""],d,k,s,u,v;s=g.$viewValue;
+u=L(e)||[];var A=I?Object.keys(u).sort():u,x,B,H,E,P={};v=l(s);var N=!1,U,W;R={};for(E=0;H=A.length,E<H;E++){x=E;if(I&&(x=A[E],"$"===x.charAt(0)))continue;B=u[x];d=h(M,x,B)||"";(k=a[d])||(k=a[d]=[],c.push(d));d=v(x,B);N=N||d;B=h(z,x,B);B=y(B)?B:"";W=K?K(e,T):I?A[E]:E;K&&(R[W]=x);k.push({id:W,label:B,selected:d})}t||(w||null===s?a[""].unshift({id:"",label:"",selected:!N}):N||a[""].unshift({id:"?",label:"",selected:!0}));x=0;for(A=c.length;x<A;x++){d=c[x];k=a[d];S.length<=x?(s={element:D.clone().attr("label",
+d),label:k.label},u=[s],S.push(u),f.append(s.element)):(u=S[x],s=u[0],s.label!=d&&s.element.attr("label",s.label=d));N=null;E=0;for(H=k.length;E<H;E++)d=k[E],(v=u[E+1])?(N=v.element,v.label!==d.label&&(n(P,v.label,!1),n(P,d.label,!0),N.text(v.label=d.label),N.prop("label",v.label)),v.id!==d.id&&N.val(v.id=d.id),N[0].selected!==d.selected&&(N.prop("selected",v.selected=d.selected),Ra&&N.prop("selected",v.selected))):(""===d.id&&w?U=w:(U=C.clone()).val(d.id).prop("selected",d.selected).attr("selected",
+d.selected).prop("label",d.label).text(d.label),u.push(v={element:U,label:d.label,id:d.id,selected:d.selected}),n(P,d.label,!0),N?N.after(U):s.element.append(U),N=U);for(E++;u.length>E;)d=u.pop(),n(P,d.label,!1),d.element.remove()}for(;S.length>x;){k=S.pop();for(E=1;E<k.length;++E)n(P,k[E].label,!1);k[0].element.remove()}r(P,function(a,c){0<a?q.addOption(c):0>a&&q.removeOption(c)})}var v;if(!(v=s.match(d)))throw gg("iexp",s,xa(f));var z=c(v[2]||v[1]),A=v[4]||v[6],B=/ as /.test(v[0])&&v[1],x=B?c(B):
+null,I=v[5],M=c(v[3]||""),E=c(v[2]?v[1]:A),L=c(v[7]),K=v[8]?c(v[8]):null,R={},S=[[{element:f,label:""}]],T={};w&&(a(w)(e),w.removeClass("ng-scope"),w.remove());f.empty();f.on("change",function(){e.$apply(function(){var a=L(e)||[],c;if(t)c=[],r(f.val(),function(d){d=K?R[d]:d;c.push("?"===d?u:""===d?null:h(x?x:E,d,a[d]))});else{var d=K?R[f.val()]:f.val();c="?"===d?u:""===d?null:h(x?x:E,d,a[d])}g.$setViewValue(c);p()})});g.$render=p;e.$watchCollection(L,k);e.$watchCollection(function(){var a=L(e),c;
+if(a&&H(a)){c=Array(a.length);for(var d=0,f=a.length;d<f;d++)c[d]=h(z,d,a[d])}else if(a)for(d in c={},a)a.hasOwnProperty(d)&&(c[d]=h(z,d,a[d]));return c},k);t&&e.$watchCollection(function(){return g.$modelValue},k)}if(l[1]){var q=l[0];l=l[1];var t=h.multiple,s=h.ngOptions,w=!1,v,m=!1,C=B(W.createElement("option")),D=B(W.createElement("optgroup")),z=C.clone();h=0;for(var A=g.children(),x=A.length;h<x;h++)if(""===A[h].value){v=w=A.eq(h);break}q.init(l,w,z);t&&(l.$isEmpty=function(a){return!a||0===a.length});
+s?p(e,g,l):t?n(e,g,l):k(e,g,l,q)}}}}],Yd=["$interpolate",function(a){var c={addOption:A,removeOption:A};return{restrict:"E",priority:100,compile:function(d,e){if(D(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),n=k.data("$selectController")||k.parent().data("$selectController");n&&n.databound||(n=c);f?a.$watch(f,function(a,c){e.$set("value",a);c!==a&&n.removeOption(c);n.addOption(a,d)}):n.addOption(e.value,d);d.on("$destroy",function(){n.removeOption(e.value)})}}}}],
+Xd=ea({restrict:"E",terminal:!1}),Ac=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}},zc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){x(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw S("ngPattern")("noregexp",g,a,xa(c));f=
+a||u;e.$validate()});e.$validators.pattern=function(a,c){return e.$isEmpty(c)||D(f)||f.test(c)}}}}},Cc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=aa(a);f=isNaN(a)?-1:a;e.$validate()});e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Bc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=aa(a)||0;e.$validate()});e.$validators.minlength=
+function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};R.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(Nd(),Pd(ca),B(W).ready(function(){Jd(W,tc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>');
+//# sourceMappingURL=angular.min.js.map
diff --git a/afb-client/bower_components/angular/angular.min.js.gzip b/afb-client/bower_components/angular/angular.min.js.gzip
new file mode 100644
index 0000000..ede8ca3
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.min.js.gzip
Binary files differ
diff --git a/afb-client/bower_components/angular/angular.min.js.map b/afb-client/bower_components/angular/angular.min.js.map
new file mode 100644
index 0000000..3104bba
--- /dev/null
+++ b/afb-client/bower_components/angular/angular.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular.min.js",
+"lineCount":252,
+"mappings":"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",
+"sources":["angular.js"],
+"names":["window","document","undefined","minErr","isArrayLike","obj","isWindow","length","Object","nodeType","NODE_TYPE_ELEMENT","isString","isArray","forEach","iterator","context","key","isFunction","hasOwnProperty","call","isPrimitive","forEachSorted","keys","sort","i","reverseParams","iteratorFn","value","nextUid","uid","setHashKey","h","$$hashKey","extend","dst","ii","arguments","j","jj","int","str","parseInt","inherit","parent","extra","create","noop","identity","$","valueFn","isUndefined","isDefined","isObject","isNumber","isDate","toString","isRegExp","isScope","$evalAsync","$watch","isBoolean","isElement","node","nodeName","prop","attr","find","makeMap","items","split","nodeName_","element","lowercase","arrayRemove","array","index","indexOf","splice","copy","source","destination","stackSource","stackDest","ngMinErr","push","result","Date","getTime","RegExp","match","lastIndex","emptyObject","getPrototypeOf","shallowCopy","src","charAt","equals","o1","o2","t1","t2","keySet","concat","array1","array2","slice","bind","self","fn","curryArgs","startIndex","apply","toJsonReplacer","val","toJson","pretty","JSON","stringify","fromJson","json","parse","startingTag","jqLite","clone","empty","e","elemHtml","append","html","NODE_TYPE_TEXT","replace","tryDecodeURIComponent","decodeURIComponent","parseKeyValue","keyValue","key_value","toKeyValue","parts","arrayValue","encodeUriQuery","join","encodeUriSegment","pctEncodeSpaces","encodeURIComponent","getNgAttribute","ngAttr","ngAttrPrefixes","angularInit","bootstrap","appElement","module","config","prefix","name","hasAttribute","getAttribute","candidate","querySelector","strictDi","modules","defaultConfig","doBootstrap","injector","tag","unshift","$provide","debugInfoEnabled","$compileProvider","createInjector","invoke","bootstrapApply","scope","compile","$apply","data","NG_ENABLE_DEBUG_INFO","NG_DEFER_BOOTSTRAP","test","angular","resumeBootstrap","angular.resumeBootstrap","extraModules","resumeDeferredBootstrap","reloadWithDebugInfo","location","reload","getTestability","rootElement","get","snake_case","separator","SNAKE_CASE_REGEXP","letter","pos","toLowerCase","bindJQuery","originalCleanData","bindJQueryFired","jQuery","on","JQLitePrototype","isolateScope","controller","inheritedData","cleanData","jQuery.cleanData","elems","events","skipDestroyOnNextJQueryCleanData","elem","_data","$destroy","triggerHandler","JQLite","assertArg","arg","reason","assertArgFn","acceptArrayAnnotation","constructor","assertNotHasOwnProperty","getter","path","bindFnToScope","lastInstance","len","getBlockNodes","nodes","endNode","blockNodes","nextSibling","createMap","setupModuleLoader","ensure","factory","$injectorMinErr","$$minErr","requires","configFn","invokeLater","provider","method","insertMethod","queue","invokeQueue","moduleInstance","configBlocks","runBlocks","_invokeQueue","_configBlocks","_runBlocks","service","constant","animation","filter","directive","run","block","publishExternalAPI","version","uppercase","counter","csp","angularModule","$LocaleProvider","ngModule","$$sanitizeUri","$$SanitizeUriProvider","$CompileProvider","a","htmlAnchorDirective","input","inputDirective","textarea","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","pattern","patternDirective","ngPattern","required","requiredDirective","ngRequired","minlength","minlengthDirective","ngMinlength","maxlength","maxlengthDirective","ngMaxlength","ngValue","ngValueDirective","ngModelOptions","ngModelOptionsDirective","ngIncludeFillContentDirective","ngAttributeAliasDirectives","ngEventDirectives","$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","$$q","$$QProvider","$sce","$SceProvider","$sceDelegate","$SceDelegateProvider","$sniffer","$SnifferProvider","$templateCache","$TemplateCacheProvider","$templateRequest","$TemplateRequestProvider","$$testability","$$TestabilityProvider","$timeout","$TimeoutProvider","$window","$WindowProvider","$$rAF","$$RAFProvider","$$asyncCallback","$$AsyncCallbackProvider","$$jqLite","$$jqLiteProvider","camelCase","SPECIAL_CHARS_REGEXP","_","offset","toUpperCase","MOZ_HACK_REGEXP","jqLiteAcceptsData","NODE_TYPE_DOCUMENT","jqLiteBuildFragment","tmp","fragment","createDocumentFragment","HTML_REGEXP","appendChild","createElement","TAG_NAME_REGEXP","exec","wrap","wrapMap","_default","innerHTML","XHTML_TAG_REGEXP","lastChild","childNodes","firstChild","textContent","createTextNode","argIsString","trim","jqLiteMinErr","parsed","SINGLE_TAG_REGEXP","jqLiteAddNodes","jqLiteClone","cloneNode","jqLiteDealoc","onlyDescendants","jqLiteRemoveData","querySelectorAll","descendants","l","jqLiteOff","type","unsupported","expandoStore","jqLiteExpandoStore","handle","listenerFns","removeEventListener","expandoId","ng339","jqCache","createIfNecessary","jqId","jqLiteData","isSimpleSetter","isSimpleGetter","massGetter","jqLiteHasClass","selector","jqLiteRemoveClass","cssClasses","setAttribute","cssClass","jqLiteAddClass","existingClasses","root","elements","jqLiteController","jqLiteInheritedData","documentElement","names","parentNode","NODE_TYPE_DOCUMENT_FRAGMENT","host","jqLiteEmpty","removeChild","jqLiteRemove","keepData","jqLiteDocumentLoaded","action","win","readyState","setTimeout","getBooleanAttrName","booleanAttr","BOOLEAN_ATTR","BOOLEAN_ELEMENTS","getAliasedAttrName","ALIASED_ATTR","createEventHandler","eventHandler","event","isDefaultPrevented","event.isDefaultPrevented","defaultPrevented","eventFns","eventFnsLength","immediatePropagationStopped","originalStopImmediatePropagation","stopImmediatePropagation","event.stopImmediatePropagation","stopPropagation","isImmediatePropagationStopped","event.isImmediatePropagationStopped","$get","this.$get","hasClass","classes","addClass","removeClass","hashKey","nextUidFn","objType","HashMap","isolatedUid","this.nextUid","put","anonFn","args","fnText","STRIP_COMMENTS","FN_ARGS","modulesToLoad","supportObject","delegate","provider_","providerInjector","instantiate","providerCache","providerSuffix","enforceReturnValue","enforcedReturnValue","instanceInjector","factoryFn","enforce","loadModules","moduleFn","runInvokeQueue","invokeArgs","loadedModules","message","stack","createInternalInjector","cache","getService","serviceName","caller","INSTANTIATING","err","shift","locals","$inject","$$annotate","Type","instance","prototype","returnedValue","annotate","has","$injector","instanceCache","decorator","decorFn","origProvider","orig$get","origProvider.$get","origInstance","$delegate","autoScrollingEnabled","disableAutoScrolling","this.disableAutoScrolling","getFirstAnchor","list","Array","some","scrollTo","scrollIntoView","scroll","yOffset","getComputedStyle","position","getBoundingClientRect","bottom","elemTop","top","scrollBy","hash","elm","getElementById","getElementsByName","autoScrollWatch","autoScrollWatchAction","newVal","oldVal","supported","Browser","completeOutstandingRequest","outstandingRequestCount","outstandingRequestCallbacks","pop","error","startPoller","interval","check","pollFns","pollFn","pollTimeout","cacheStateAndFireUrlChange","cacheState","fireUrlChange","history","state","cachedState","lastCachedState","lastBrowserUrl","url","lastHistoryState","urlChangeListeners","listener","safeDecodeURIComponent","rawDocument","clearTimeout","pendingDeferIds","isMock","$$completeOutstandingRequest","$$incOutstandingRequestCount","self.$$incOutstandingRequestCount","notifyWhenNoOutstandingRequests","self.notifyWhenNoOutstandingRequests","callback","addPollFn","self.addPollFn","href","baseElement","reloadLocation","self.url","sameState","sameBase","stripHash","substr","self.state","urlChangeInit","onUrlChange","self.onUrlChange","$$checkUrlChange","baseHref","self.baseHref","lastCookies","lastCookieString","cookiePath","cookies","self.cookies","cookieLength","cookie","warn","cookieArray","substring","defer","self.defer","delay","timeoutId","cancel","self.defer.cancel","deferId","cacheFactory","cacheId","options","refresh","entry","freshEnd","staleEnd","n","link","p","nextEntry","prevEntry","caches","size","stats","id","capacity","Number","MAX_VALUE","lruHash","lruEntry","remove","removeAll","destroy","info","cacheFactory.info","cacheFactory.get","$$sanitizeUriProvider","parseIsolateBindings","directiveName","LOCAL_REGEXP","bindings","definition","scopeName","$compileMinErr","mode","collection","optional","attrName","hasDirectives","COMMENT_DIRECTIVE_REGEXP","CLASS_DIRECTIVE_REGEXP","ALL_OR_NOTHING_ATTRS","REQUIRE_PREFIX_REGEXP","EVENT_HANDLER_ATTR_REGEXP","this.directive","registerDirective","directiveFactory","Suffix","directives","priority","require","restrict","$$isolateBindings","aHrefSanitizationWhitelist","this.aHrefSanitizationWhitelist","regexp","imgSrcSanitizationWhitelist","this.imgSrcSanitizationWhitelist","this.debugInfoEnabled","enabled","safeAddClass","$element","className","$compileNodes","transcludeFn","maxPriority","ignoreDirective","previousCompileContext","nodeValue","compositeLinkFn","compileNodes","$$addScopeClass","namespace","publicLinkFn","cloneConnectFn","parentBoundTranscludeFn","transcludeControllers","futureParentElement","$$boundTransclude","$linkNode","wrapTemplate","controllerName","$$addScopeInfo","nodeList","$rootElement","childLinkFn","childScope","childBoundTranscludeFn","stableNodeList","nodeLinkFnFound","linkFns","idx","nodeLinkFn","$new","transcludeOnThisElement","createBoundTranscludeFn","transclude","elementTranscludeOnThisElement","templateOnThisElement","attrs","linkFnFound","Attributes","collectDirectives","applyDirectivesToNode","$$element","terminal","previousBoundTranscludeFn","elementTransclusion","boundTranscludeFn","transcludedScope","cloneFn","controllers","containingScope","$$transcluded","attrsMap","$attr","addDirective","directiveNormalize","isNgAttr","nAttrs","attributes","attrStartName","attrEndName","ngAttrName","NG_ATTR_BINDING","PREFIX_REGEXP","directiveNName","directiveIsMultiElement","nName","addAttrInterpolateDirective","animVal","addTextInterpolateDirective","NODE_TYPE_COMMENT","byPriority","groupScan","attrStart","attrEnd","depth","groupElementsLinkFnWrapper","linkFn","compileNode","templateAttrs","jqCollection","originalReplaceDirective","preLinkFns","postLinkFns","addLinkFns","pre","post","newIsolateScopeDirective","$$isolateScope","cloneAndAnnotateFn","getControllers","elementControllers","retrievalMethod","$searchElement","linkNode","controllersBoundTransclude","cloneAttachFn","hasElementTranscludeDirective","scopeToChild","controllerDirectives","$scope","$attrs","$transclude","controllerInstance","controllerAs","templateDirective","$$originalDirective","isolateScopeController","isolateBindingContext","identifier","bindToController","lastValue","parentGet","parentSet","compare","$observe","$$observers","$$scope","literal","b","assign","parentValueWatch","parentValue","$stateful","unwatch","$watchCollection","$on","invokeLinkFn","template","templateUrl","terminalPriority","newScopeDirective","nonTlbTranscludeDirective","hasTranscludeDirective","hasTemplate","$compileNode","$template","childTranscludeFn","$$start","$$end","directiveValue","assertNoDuplicate","$$tlb","createComment","replaceWith","replaceDirective","contents","denormalizeTemplate","removeComments","templateNamespace","newTemplateAttrs","templateDirectives","unprocessedDirectives","markDirectivesAsIsolate","mergeTemplateAttributes","compileTemplateUrl","Math","max","tDirectives","startAttrName","endAttrName","multiElement","srcAttr","dstAttr","$set","tAttrs","linkQueue","afterTemplateNodeLinkFn","afterTemplateChildLinkFn","beforeTemplateCompileNode","origAsyncDirective","derivedSyncDirective","then","content","tempTemplateAttrs","beforeTemplateLinkNode","linkRootElement","$$destroyed","oldClasses","delayedNodeLinkFn","ignoreChildLinkFn","diff","what","previousDirective","text","interpolateFn","textInterpolateCompileFn","templateNode","templateNodeParent","hasCompileParent","$$addBindingClass","textInterpolateLinkFn","$$addBindingInfo","expressions","interpolateFnWatchAction","wrapper","getTrustedContext","attrNormalizedName","HTML","RESOURCE_URL","allOrNothing","trustedContext","attrInterpolatePreLinkFn","newValue","$$inter","oldValue","$updateClass","elementsToRemove","newNode","firstElementToRemove","removeCount","j2","replaceChild","expando","k","kk","annotation","attributesToCopy","$normalize","$addClass","classVal","$removeClass","newClasses","toAdd","tokenDifference","toRemove","writeAttr","booleanKey","aliasedKey","observer","trimmedSrcset","srcPattern","rawUris","nbrUrisWith2parts","floor","innerIdx","lastTuple","removeAttr","listeners","startSymbol","endSymbol","binding","isolated","noTemplate","dataName","str1","str2","values","tokens1","tokens2","token","jqNodes","globals","CNTRL_REG","register","this.register","allowGlobals","this.allowGlobals","addIdentifier","expression","later","ident","$controllerMinErr","controllerPrototype","exception","cause","defaultHttpResponseTransform","headers","tempData","JSON_PROTECTION_PREFIX","contentType","jsonStart","JSON_START","JSON_ENDS","parseHeaders","line","headersGetter","headersObj","transformData","status","fns","defaults","transformResponse","transformRequest","d","common","CONTENT_TYPE_APPLICATION_JSON","patch","xsrfCookieName","xsrfHeaderName","useApplyAsync","this.useApplyAsync","interceptorFactories","interceptors","requestConfig","response","resp","reject","executeHeaderFns","headerContent","processedHeaders","headerFn","header","mergeHeaders","defHeaders","reqHeaders","defHeaderName","reqHeaderName","lowercaseDefHeaderName","chain","serverRequest","reqData","withCredentials","sendReq","promise","when","reversedInterceptors","interceptor","request","requestError","responseError","thenFn","rejectFn","success","promise.success","promise.error","done","headersString","statusText","resolveHttpPromise","resolvePromise","$applyAsync","$$phase","deferred","resolve","resolvePromiseWithResult","removePendingReq","pendingRequests","cachedResp","buildUrl","params","defaultCache","xsrfValue","urlIsSameOrigin","timeout","responseType","v","toISOString","interceptorFactory","createShortMethods","createShortMethodsWithData","createXhr","XMLHttpRequest","createHttpBackend","callbacks","$browserDefer","jsonpReq","callbackId","async","body","called","addEventListener","timeoutRequest","jsonpDone","xhr","abort","completeRequest","open","setRequestHeader","onload","xhr.onload","responseText","urlResolve","protocol","getAllResponseHeaders","onerror","onabort","send","this.startSymbol","this.endSymbol","escape","ch","mustHaveExpression","unescapeText","escapedStartRegexp","escapedEndRegexp","parseStringifyInterceptor","getTrusted","valueOf","newErr","$interpolateMinErr","endIndex","parseFns","textLength","expressionPositions","startSymbolLength","exp","endSymbolLength","compute","interpolationFn","$$watchDelegate","objectEquality","$watchGroup","interpolateFnWatcher","oldValues","currValue","$interpolate.startSymbol","$interpolate.endSymbol","count","invokeApply","setInterval","clearInterval","iteration","skipApply","$$intervalId","tick","notify","intervals","interval.cancel","NUMBER_FORMATS","DECIMAL_SEP","GROUP_SEP","PATTERNS","minInt","minFrac","maxFrac","posPre","posSuf","negPre","negSuf","gSize","lgSize","CURRENCY_SYM","DATETIME_FORMATS","MONTH","SHORTMONTH","DAY","SHORTDAY","AMPMS","medium","fullDate","longDate","mediumDate","shortDate","mediumTime","shortTime","ERANAMES","ERAS","pluralCat","num","encodePath","segments","parseAbsoluteUrl","absoluteUrl","locationObj","parsedUrl","$$protocol","$$host","hostname","$$port","port","DEFAULT_PORTS","parseAppUrl","relativeUrl","prefixed","$$path","pathname","$$search","search","$$hash","beginsWith","begin","whole","trimEmptyHash","LocationHtml5Url","appBase","appBaseNoFile","basePrefix","$$html5","$$parse","this.$$parse","pathUrl","$locationMinErr","$$compose","this.$$compose","$$url","$$absUrl","$$parseLinkUrl","this.$$parseLinkUrl","relHref","appUrl","prevAppUrl","rewrittenUrl","LocationHashbangUrl","hashPrefix","withoutBaseUrl","withoutHashUrl","windowsFilePathExp","base","firstPathSegmentMatch","LocationHashbangInHtml5Url","locationGetter","property","locationGetterSetter","preprocess","html5Mode","requireBase","rewriteLinks","this.hashPrefix","this.html5Mode","setBrowserUrlWithFallback","oldUrl","oldState","$$state","afterLocationChange","$broadcast","absUrl","LocationMode","initialUrl","lastIndexOf","IGNORE_URI_REGEXP","ctrlKey","metaKey","shiftKey","which","button","target","absHref","preventDefault","initializing","newUrl","newState","$digest","$locationWatch","currentReplace","$$replace","urlOrStateChanged","debug","debugEnabled","this.debugEnabled","flag","formatError","Error","sourceURL","consoleLog","console","logFn","log","hasApply","arg1","arg2","ensureSafeMemberName","fullExpression","$parseMinErr","getStringValue","ensureSafeObject","children","isConstant","setter","setValue","fullExp","propertyObj","isPossiblyDangerousMemberName","cspSafeGetterFn","key0","key1","key2","key3","key4","expensiveChecks","eso","o","eso0","eso1","eso2","eso3","eso4","cspSafeGetter","pathVal","getterFnWithEnsureSafeObject","s","getterFn","getterFnCache","getterFnCacheExpensive","getterFnCacheDefault","pathKeys","pathKeysLength","code","needsEnsureSafeObject","lookupJs","evaledFnGetter","Function","sharedGetter","fn.assign","getValueOf","objectValueOf","cacheDefault","cacheExpensive","wrapSharedExpression","wrapped","collectExpressionInputs","inputs","expressionInputDirtyCheck","oldValueOfValue","inputsWatchDelegate","parsedExpression","inputExpressions","$$inputs","lastResult","oldInputValue","expressionInputWatch","newInputValue","oldInputValueOfValues","expressionInputsWatch","changed","oneTimeWatchDelegate","oneTimeWatch","oneTimeListener","old","$$postDigest","oneTimeLiteralWatchDelegate","isAllDefined","allDefined","constantWatchDelegate","constantWatch","constantListener","addInterceptor","interceptorFn","watchDelegate","regularInterceptedExpression","oneTimeInterceptedExpression","$parseOptions","$parseOptionsExpensive","oneTime","cacheKey","parseOptions","lexer","Lexer","parser","Parser","qFactory","nextTick","exceptionHandler","callOnce","resolveFn","Promise","simpleBind","scheduleProcessQueue","processScheduled","pending","Deferred","$qMinErr","TypeError","onFulfilled","onRejected","progressBack","catch","finally","handleCallback","$$reject","$$resolve","progress","makePromise","resolved","isResolved","callbackOutput","errback","$Q","Q","resolver","all","promises","results","flush","taskQueue","task","taskCount","queueFn","asyncFn","cancelLastRAF","rafFn","cancelQueueFn","requestAnimationFrame","webkitRequestAnimationFrame","cancelAnimationFrame","webkitCancelAnimationFrame","webkitCancelRequestAnimationFrame","rafSupported","timer","createChildScopeClass","ChildScope","$$watchers","$$nextSibling","$$childHead","$$childTail","$$listeners","$$listenerCount","$id","$$ChildScope","TTL","$rootScopeMinErr","lastDirtyWatch","applyAsyncId","digestTtl","this.digestTtl","destroyChildScope","$event","currentScope","Scope","$parent","$$prevSibling","$root","beginPhase","phase","decrementListenerCount","current","initWatchVal","flushApplyAsync","applyAsyncQueue","scheduleApplyAsync","isolate","child","watchExp","watcher","last","eq","deregisterWatch","watchExpressions","watchGroupAction","changeReactionScheduled","firstRun","newValues","deregisterFns","shouldCall","deregisterWatchGroup","expr","unwatchFn","watchGroupSubAction","$watchCollectionInterceptor","_value","bothNaN","newItem","oldItem","internalArray","oldLength","changeDetected","newLength","internalObject","veryOldValue","trackVeryOldValue","changeDetector","initRun","$watchCollectionAction","watch","watchers","dirty","ttl","watchLog","logIdx","asyncTask","asyncQueue","$eval","isNaN","msg","next","postDigestQueue","eventName","this.$watchGroup","$applyAsyncExpression","namedListeners","indexOfListener","$emit","targetScope","listenerArgs","$$asyncQueue","$$postDigestQueue","$$applyAsyncQueue","sanitizeUri","uri","isImage","regex","normalizedVal","adjustMatcher","matcher","$sceMinErr","escapeForRegexp","adjustMatchers","matchers","adjustedMatchers","SCE_CONTEXTS","resourceUrlWhitelist","resourceUrlBlacklist","this.resourceUrlWhitelist","this.resourceUrlBlacklist","matchUrl","generateHolderType","Base","holderType","trustedValue","$$unwrapTrustedValue","this.$$unwrapTrustedValue","holderType.prototype.valueOf","holderType.prototype.toString","htmlSanitizer","trustedValueHolderBase","byType","CSS","URL","JS","trustAs","Constructor","maybeTrusted","allowed","this.enabled","msie","sce","isEnabled","sce.isEnabled","sce.getTrusted","parseAs","sce.parseAs","enumValue","lName","eventSupport","android","userAgent","navigator","boxee","vendorPrefix","vendorRegex","bodyStyle","transitions","animations","webkitTransition","webkitAnimation","pushState","hasEvent","divElm","handleRequestFn","tpl","ignoreRequestError","totalPendingRequests","getTrustedResourceUrl","transformer","httpOptions","handleError","testability","testability.findBindings","opt_exactMatch","getElementsByClassName","matches","dataBinding","bindingName","testability.findModels","prefixes","attributeEquals","testability.getLocation","testability.setLocation","testability.whenStable","deferreds","$$timeoutId","timeout.cancel","urlParsingNode","requestUrl","originUrl","filters","suffix","currencyFilter","dateFilter","filterFilter","jsonFilter","limitToFilter","lowercaseFilter","numberFilter","orderByFilter","uppercaseFilter","comparator","matchAgainstAnyProp","expressionType","predicateFn","createPredicateFn","shouldMatchPrimitives","actual","expected","item","deepCompare","dontMatchWholeObject","actualType","expectedType","expectedVal","matchAnyProperty","actualVal","$locale","formats","amount","currencySymbol","fractionSize","formatNumber","number","groupSep","decimalSep","isFinite","isNegative","abs","numStr","formatedText","hasExponent","toFixed","parseFloat","fractionLen","min","round","fraction","lgroup","group","padNumber","digits","neg","dateGetter","date","dateStrGetter","shortForm","getFirstThursdayOfYear","year","dayOfWeekOnFirst","getDay","weekGetter","firstThurs","getFullYear","thisThurs","getMonth","getDate","eraGetter","jsonStringToDate","string","R_ISO8601_STR","tzHour","tzMin","dateSetter","setUTCFullYear","setFullYear","timeSetter","setUTCHours","setHours","m","ms","format","timezone","NUMBER_STRING","DATE_FORMATS_SPLIT","setMinutes","getMinutes","getTimezoneOffset","DATE_FORMATS","object","spacing","limit","Infinity","sortPredicate","reverseOrder","reverseComparator","comp","descending","objectToString","v1","v2","map","predicate","ngDirective","FormController","controls","parentForm","$$parentForm","nullFormCtrl","$error","$$success","$pending","$name","$dirty","$pristine","$valid","$invalid","$submitted","$addControl","$rollbackViewValue","form.$rollbackViewValue","control","$commitViewValue","form.$commitViewValue","form.$addControl","$$renameControl","form.$$renameControl","newName","oldName","$removeControl","form.$removeControl","$setValidity","addSetValidityMethod","ctrl","set","unset","$setDirty","form.$setDirty","PRISTINE_CLASS","DIRTY_CLASS","$setPristine","form.$setPristine","setClass","SUBMITTED_CLASS","$setUntouched","form.$setUntouched","$setSubmitted","form.$setSubmitted","stringBasedInputType","$formatters","$isEmpty","baseInputType","composing","ev","ngTrim","$viewValue","$$hasNativeValidators","$setViewValue","deferListener","origValue","keyCode","$render","ctrl.$render","createDateParser","mapping","iso","ISO_DATE_REGEXP","yyyy","MM","dd","HH","getHours","mm","ss","getSeconds","sss","getMilliseconds","part","NaN","createDateInputType","parseDate","dynamicDateInputType","isValidDate","parseObservedDateValue","badInputChecker","$options","previousDate","$$parserName","$parsers","parsedDate","ngModelMinErr","timezoneOffset","ngMin","minVal","$validators","ctrl.$validators.min","$validate","ngMax","maxVal","ctrl.$validators.max","validity","VALIDITY_STATE_PROPERTY","badInput","typeMismatch","parseConstantExpr","fallback","parseFn","classDirective","arrayDifference","arrayClasses","digestClassCounts","classCounts","classesToUpdate","ngClassWatchAction","$index","old$index","mod","cachedToggleClass","switchValue","classCache","toggleValidationCss","validationErrorKey","isValid","VALID_CLASS","INVALID_CLASS","setValidity","isObjectEmpty","PENDING_CLASS","combinedState","REGEX_STRING_REGEXP","documentMode","isActive_","active","full","major","minor","dot","codeName","JQLite._data","MOUSE_EVENT_MAP","mouseleave","mouseenter","optgroup","tbody","tfoot","colgroup","caption","thead","th","td","ready","trigger","fired","removeData","removeAttribute","css","NODE_TYPE_ATTRIBUTE","lowercasedName","specified","getNamedItem","ret","getText","$dv","multiple","selected","nodeCount","jqLiteOn","types","related","relatedTarget","contains","off","one","onFn","replaceNode","insertBefore","contentDocument","prepend","wrapNode","detach","after","newElement","toggleClass","condition","classCondition","nextElementSibling","getElementsByTagName","extraParameters","dummyEvent","handlerArgs","eventFnsCopy","arg3","unbind","FN_ARG_SPLIT","FN_ARG","argDecl","underscore","$animateMinErr","$$selectors","classNameFilter","this.classNameFilter","$$classNameFilter","runAnimationPostDigest","cancelFn","$$cancelFn","defer.promise.$$cancelFn","ngAnimatePostDigest","ngAnimateNotifyComplete","resolveElementClasses","hasClasses","cachedClassManipulation","op","asyncPromise","currentDefer","applyStyles","styles","from","to","animate","enter","leave","move","$$addClassImmediately","$$removeClassImmediately","add","createdCache","STORAGE_KEY","$$setClassImmediately","APPLICATION_JSON","PATH_MATCH","locationPrototype","paramValue","Location","Location.prototype.state","CALL","APPLY","BIND","CONSTANTS","null","true","false","constantGetter","OPERATORS","+","-","*","/","%","===","!==","==","!=","<",">","<=",">=","&&","||","!","ESCAPE","lex","tokens","readString","peek","readNumber","isIdent","readIdent","is","isWhitespace","ch2","ch3","op2","op3","op1","operator","throwError","chars","isExpOperator","start","end","colStr","peekCh","quote","rawString","hex","String","fromCharCode","rep","ZERO","statements","primary","expect","filterChain","consume","arrayDeclaration","functionCall","objectIndex","fieldAccess","peekToken","e1","e2","e3","e4","peekAhead","t","unaryFn","right","$parseUnaryFn","binaryFn","left","isBranching","$parseBinaryFn","$parseConstant","$parseStatements","inputFn","argsFn","$parseFilter","every","assignment","ternary","$parseAssignment","logicalOR","middle","$parseTernary","logicalAND","equality","relational","additive","multiplicative","unary","$parseFieldAccess","indexFn","$parseObjectIndex","fnGetter","contextGetter","expressionText","$parseFunctionCall","elementFns","$parseArrayLiteral","valueFns","$parseObjectLiteral","yy","y","MMMM","MMM","M","H","hh","EEEE","EEE","ampmGetter","Z","timeZoneGetter","zone","paddedZone","ww","w","G","GG","GGG","GGGG","longEraGetter","xlinkHref","propName","normalized","ngBooleanAttrWatchAction","htmlAttr","ngAttrAliasWatchAction","nullFormRenameControl","formDirectiveFactory","isNgForm","ngFormCompile","formElement","nameAttr","ngFormPreLink","handleFormSubmission","parentFormCtrl","URL_REGEXP","EMAIL_REGEXP","NUMBER_REGEXP","DATE_REGEXP","DATETIMELOCAL_REGEXP","WEEK_REGEXP","MONTH_REGEXP","TIME_REGEXP","inputType","textInputType","weekParser","isoWeek","existingDate","week","minutes","hours","seconds","milliseconds","addDays","numberInputType","urlInputType","ctrl.$validators.url","modelValue","viewValue","emailInputType","email","ctrl.$validators.email","radioInputType","checked","checkboxInputType","trueValue","ngTrueValue","falseValue","ngFalseValue","ctrl.$isEmpty","ctrls","CONSTANT_VALUE_REGEXP","tplAttr","ngValueConstantLink","ngValueLink","valueWatchAction","$compile","ngBindCompile","templateElement","ngBindLink","ngBindWatchAction","ngBindTemplateCompile","ngBindTemplateLink","ngBindHtmlCompile","tElement","ngBindHtmlGetter","ngBindHtmlWatch","ngBindHtmlLink","ngBindHtmlWatchAction","getTrustedHtml","$viewChangeListeners","forceAsyncEvents","ngEventHandler","previousElements","ngIfWatchAction","newScope","srcExp","onloadExp","autoScrollExp","autoscroll","changeCounter","previousElement","currentElement","cleanupLastIncludeContent","ngIncludeWatchAction","afterAnimation","thisChangeId","namespaceAdaptedClone","trimValues","NgModelController","$modelValue","$$rawModelValue","$asyncValidators","$untouched","$touched","parsedNgModel","parsedNgModelAssign","ngModelGet","ngModelSet","pendingDebounce","parserValid","$$setOptions","this.$$setOptions","getterSetter","invokeModelGetter","invokeModelSetter","$$$p","this.$isEmpty","currentValidationRunId","this.$setPristine","this.$setDirty","this.$setUntouched","UNTOUCHED_CLASS","TOUCHED_CLASS","$setTouched","this.$setTouched","this.$rollbackViewValue","$$lastCommittedViewValue","this.$validate","prevValid","prevModelValue","allowInvalid","$$runValidators","allValid","$$writeModelToScope","this.$$runValidators","doneCallback","processSyncValidators","syncValidatorsValid","validator","processAsyncValidators","validatorPromises","validationDone","localValidationRunId","processParseErrors","errorKey","this.$commitViewValue","$$parseAndValidate","this.$$parseAndValidate","this.$$writeModelToScope","this.$setViewValue","updateOnDefault","$$debounceViewValueCommit","this.$$debounceViewValueCommit","debounceDelay","debounce","ngModelWatch","formatters","ngModelCompile","ngModelPreLink","modelCtrl","formCtrl","ngModelPostLink","updateOn","DEFAULT_REGEXP","that","BRACE","IS_WHEN","updateElementText","newText","numberExp","whenExp","whens","whensExpFns","braceReplacement","watchRemover","lastCount","attributeName","tmpMatch","whenKey","ngPluralizeWatchAction","countIsNaN","ngRepeatMinErr","updateScope","valueIdentifier","keyIdentifier","arrayLength","$first","$last","$middle","$odd","$even","ngRepeatCompile","ngRepeatEndComment","lhs","rhs","aliasAs","trackByExp","trackByExpGetter","trackByIdExpFn","trackByIdArrayFn","trackByIdObjFn","hashFnLocals","ngRepeatLink","lastBlockMap","ngRepeatAction","previousNode","nextNode","nextBlockMap","collectionLength","trackById","collectionKeys","nextBlockOrder","trackByIdFn","itemKey","blockKey","ngRepeatTransclude","ngShowWatchAction","NG_HIDE_CLASS","tempClasses","NG_HIDE_IN_PROGRESS_CLASS","ngHideWatchAction","ngStyleWatchAction","newStyles","oldStyles","ngSwitchController","cases","selectedTranscludes","selectedElements","previousLeaveAnimations","selectedScopes","spliceFactory","ngSwitchWatchAction","selectedTransclude","caseElement","selectedScope","anchor","ngOptionsMinErr","NG_OPTIONS_REGEXP","nullModelCtrl","optionsMap","ngModelCtrl","unknownOption","databound","init","self.init","ngModelCtrl_","nullOption_","unknownOption_","addOption","self.addOption","removeOption","self.removeOption","hasOption","renderUnknownOption","self.renderUnknownOption","unknownVal","self.hasOption","setupAsSingle","selectElement","selectCtrl","ngModelCtrl.$render","emptyOption","setupAsMultiple","lastView","selectMultipleWatch","setupAsOptions","callExpression","exprFn","valueName","keyName","createIsSelectedFn","selectedSet","trackFn","trackIndex","isSelected","compareValueFn","selectAsFn","scheduleRendering","renderScheduled","render","updateLabelMap","labelMap","label","added","optionGroups","optionGroupNames","optionGroupName","optionGroup","existingParent","existingOptions","existingOption","valuesFn","anySelected","optionId","trackKeysCache","groupByFn","displayFn","nullOption","groupIndex","groupLength","optionGroupsCache","optGroupTemplate","lastElement","optionTemplate","optionsExp","selectAs","track","selectionChanged","selectedKey","viewValueFn","getLabels","toDisplay","ngModelCtrl.$isEmpty","nullSelectCtrl","selectCtrlName","interpolateWatchAction","ctrl.$validators.required","patternExp","ctrl.$validators.pattern","intVal","ctrl.$validators.maxlength","ctrl.$validators.minlength","$$csp","head"]
+}
diff --git a/afb-client/bower_components/angular/bower.json b/afb-client/bower_components/angular/bower.json
new file mode 100644
index 0000000..5bde08c
--- /dev/null
+++ b/afb-client/bower_components/angular/bower.json
@@ -0,0 +1,8 @@
+{
+ "name": "angular",
+ "version": "1.3.20",
+ "main": "./angular.js",
+ "ignore": [],
+ "dependencies": {
+ }
+}
diff --git a/afb-client/bower_components/angular/index.js b/afb-client/bower_components/angular/index.js
new file mode 100644
index 0000000..5c1aafc
--- /dev/null
+++ b/afb-client/bower_components/angular/index.js
@@ -0,0 +1,2 @@
+require('./angular');
+module.exports = angular;
diff --git a/afb-client/bower_components/angular/package.json b/afb-client/bower_components/angular/package.json
new file mode 100644
index 0000000..563bd60
--- /dev/null
+++ b/afb-client/bower_components/angular/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "angular",
+ "version": "1.3.20",
+ "description": "HTML enhanced for web apps",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/angular/angular.js.git"
+ },
+ "keywords": [
+ "angular",
+ "framework",
+ "browser",
+ "client-side"
+ ],
+ "author": "Angular Core Team <angular-core+npm@google.com>",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/angular/angular.js/issues"
+ },
+ "homepage": "http://angularjs.org"
+}