History

ModbusAdapters: Fixed security issues in Modbus configuration screen GSF.Web: Cleaned up new embedded resources

J. Ritchie Carroll committed 9 years ago

Commit 970956d1 parent 230686d36 files · +72369 −1648Browse files

Showing the changes to Source/Libraries/GSF.Web/Shared/Scripts/angular.js (1 of 36 files). Show all

Unified · Split

Source/Libraries/GSF.Web/Shared/Scripts/angular.js+31768−0
@@ -0,0 +1,31768 @@
1+/**
2+ * @license AngularJS v1.5.8
3+ * (c) 2010-2016 Google, Inc. http://angularjs.org
4+ * License: MIT
5+ */
6+(function(window) {'use strict';
7+
8+/**
9+ * @description
10+ *
11+ * This object provides a utility for producing rich Error messages within
12+ * Angular. It can be called as follows:
13+ *
14+ * var exampleMinErr = minErr('example');
15+ * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
16+ *
17+ * The above creates an instance of minErr in the example namespace. The
18+ * resulting error will have a namespaced error code of example.one. The
19+ * resulting error will replace {0} with the value of foo, and {1} with the
20+ * value of bar. The object is not restricted in the number of arguments it can
21+ * take.
22+ *
23+ * If fewer arguments are specified than necessary for interpolation, the extra
24+ * interpolation markers will be preserved in the final string.
25+ *
26+ * Since data will be parsed statically during a build step, some restrictions
27+ * are applied with respect to how minErr instances are created and called.
28+ * Instances should have names of the form namespaceMinErr for a minErr created
29+ * using minErr('namespace') . Error codes, namespaces and template strings
30+ * should all be static strings, not variables or general expressions.
31+ *
32+ * @param {string} module The namespace to use for the new minErr instance.
33+ * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
34+ * error from returned function, for cases when a particular type of error is useful.
35+ * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
36+ */
37+
38+function minErr(module, ErrorConstructor) {
39+ ErrorConstructor = ErrorConstructor || Error;
40+ return function() {
41+ var SKIP_INDEXES = 2;
42+
43+ var templateArgs = arguments,
44+ code = templateArgs[0],
45+ message = '[' + (module ? module + ':' : '') + code + '] ',
46+ template = templateArgs[1],
47+ paramPrefix, i;
48+
49+ message += template.replace(/\{\d+\}/g, function(match) {
50+ var index = +match.slice(1, -1),
51+ shiftedIndex = index + SKIP_INDEXES;
52+
53+ if (shiftedIndex < templateArgs.length) {
54+ return toDebugString(templateArgs[shiftedIndex]);
55+ }
56+
57+ return match;
58+ });
59+
60+ message += '\nhttp://errors.angularjs.org/1.5.8/' +
61+ (module ? module + '/' : '') + code;
62+
63+ for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
64+ message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
65+ encodeURIComponent(toDebugString(templateArgs[i]));
66+ }
67+
68+ return new ErrorConstructor(message);
69+ };
70+}
71+
72+/* We need to tell jshint what variables are being exported */
73+/* global angular: true,
74+ msie: true,
75+ jqLite: true,
76+ jQuery: true,
77+ slice: true,
78+ splice: true,
79+ push: true,
80+ toString: true,
81+ ngMinErr: true,
82+ angularModule: true,
83+ uid: true,
84+ REGEX_STRING_REGEXP: true,
85+ VALIDITY_STATE_PROPERTY: true,
86+
87+ lowercase: true,
88+ uppercase: true,
89+ manualLowercase: true,
90+ manualUppercase: true,
91+ nodeName_: true,
92+ isArrayLike: true,
93+ forEach: true,
94+ forEachSorted: true,
95+ reverseParams: true,
96+ nextUid: true,
97+ setHashKey: true,
98+ extend: true,
99+ toInt: true,
100+ inherit: true,
101+ merge: true,
102+ noop: true,
103+ identity: true,
104+ valueFn: true,
105+ isUndefined: true,
106+ isDefined: true,
107+ isObject: true,
108+ isBlankObject: true,
109+ isString: true,
110+ isNumber: true,
111+ isDate: true,
112+ isArray: true,
113+ isFunction: true,
114+ isRegExp: true,
115+ isWindow: true,
116+ isScope: true,
117+ isFile: true,
118+ isFormData: true,
119+ isBlob: true,
120+ isBoolean: true,
121+ isPromiseLike: true,
122+ trim: true,
123+ escapeForRegexp: true,
124+ isElement: true,
125+ makeMap: true,
126+ includes: true,
127+ arrayRemove: true,
128+ copy: true,
129+ equals: true,
130+ csp: true,
131+ jq: true,
132+ concat: true,
133+ sliceArgs: true,
134+ bind: true,
135+ toJsonReplacer: true,
136+ toJson: true,
137+ fromJson: true,
138+ convertTimezoneToLocal: true,
139+ timezoneToOffset: true,
140+ startingTag: true,
141+ tryDecodeURIComponent: true,
142+ parseKeyValue: true,
143+ toKeyValue: true,
144+ encodeUriSegment: true,
145+ encodeUriQuery: true,
146+ angularInit: true,
147+ bootstrap: true,
148+ getTestability: true,
149+ snake_case: true,
150+ bindJQuery: true,
151+ assertArg: true,
152+ assertArgFn: true,
153+ assertNotHasOwnProperty: true,
154+ getter: true,
155+ getBlockNodes: true,
156+ hasOwnProperty: true,
157+ createMap: true,
158+
159+ NODE_TYPE_ELEMENT: true,
160+ NODE_TYPE_ATTRIBUTE: true,
161+ NODE_TYPE_TEXT: true,
162+ NODE_TYPE_COMMENT: true,
163+ NODE_TYPE_DOCUMENT: true,
164+ NODE_TYPE_DOCUMENT_FRAGMENT: true,
165+*/
166+
167+////////////////////////////////////
168+
169+/**
170+ * @ngdoc module
171+ * @name ng
172+ * @module ng
173+ * @installation
174+ * @description
175+ *
176+ * # ng (core module)
177+ * The ng module is loaded by default when an AngularJS application is started. The module itself
178+ * contains the essential components for an AngularJS application to function. The table below
179+ * lists a high level breakdown of each of the services/factories, filters, directives and testing
180+ * components available within this core module.
181+ *
182+ * <div doc-module-components="ng"></div>
183+ */
184+
185+var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
186+
187+// The name of a form control's ValidityState property.
188+// This is used so that it's possible for internal tests to create mock ValidityStates.
189+var VALIDITY_STATE_PROPERTY = 'validity';
190+
191+var hasOwnProperty = Object.prototype.hasOwnProperty;
192+
193+var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
194+var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
195+
196+
197+var manualLowercase = function(s) {
198+ /* jshint bitwise: false */
199+ return isString(s)
200+ ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
201+ : s;
202+};
203+var manualUppercase = function(s) {
204+ /* jshint bitwise: false */
205+ return isString(s)
206+ ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
207+ : s;
208+};
209+
210+
211+// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
212+// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
213+// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387
214+if ('i' !== 'I'.toLowerCase()) {
215+ lowercase = manualLowercase;
216+ uppercase = manualUppercase;
217+}
218+
219+
220+var
221+ msie, // holds major version number for IE, or NaN if UA is not IE.
222+ jqLite, // delay binding since jQuery could be loaded after us.
223+ jQuery, // delay binding
224+ slice = [].slice,
225+ splice = [].splice,
226+ push = [].push,
227+ toString = Object.prototype.toString,
228+ getPrototypeOf = Object.getPrototypeOf,
229+ ngMinErr = minErr('ng'),
230+
231+ /** @name angular */
232+ angular = window.angular || (window.angular = {}),
233+ angularModule,
234+ uid = 0;
235+
236+/**
237+ * documentMode is an IE-only property
238+ * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
239+ */
240+msie = window.document.documentMode;
241+
242+
243+/**
244+ * @private
245+ * @param {*} obj
246+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
247+ * String ...)
248+ */
249+function isArrayLike(obj) {
250+
251+ // `null`, `undefined` and `window` are not array-like
252+ if (obj == null || isWindow(obj)) return false;
253+
254+ // arrays, strings and jQuery/jqLite objects are array like
255+ // * jqLite is either the jQuery or jqLite constructor function
256+ // * we have to check the existence of jqLite first as this method is called
257+ // via the forEach method when constructing the jqLite object in the first place
258+ if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
259+
260+ // Support: iOS 8.2 (not reproducible in simulator)
261+ // "length" in obj used to prevent JIT error (gh-11508)
262+ var length = "length" in Object(obj) && obj.length;
263+
264+ // NodeList objects (with `item` method) and
265+ // other objects with suitable length characteristics are array-like
266+ return isNumber(length) &&
267+ (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function');
268+
269+}
270+
271+/**
272+ * @ngdoc function
273+ * @name angular.forEach
274+ * @module ng
275+ * @kind function
276+ *
277+ * @description
278+ * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
279+ * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
280+ * is the value of an object property or an array element, `key` is the object property key or
281+ * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
282+ *
283+ * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
284+ * using the `hasOwnProperty` method.
285+ *
286+ * Unlike ES262's
287+ * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
288+ * providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
289+ * return the value provided.
290+ *
291+ ```js
292+ var values = {name: 'misko', gender: 'male'};
293+ var log = [];
294+ angular.forEach(values, function(value, key) {
295+ this.push(key + ': ' + value);
296+ }, log);
297+ expect(log).toEqual(['name: misko', 'gender: male']);
298+ ```
299+ *
300+ * @param {Object|Array} obj Object to iterate over.
301+ * @param {Function} iterator Iterator function.
302+ * @param {Object=} context Object to become context (`this`) for the iterator function.
303+ * @returns {Object|Array} Reference to `obj`.
304+ */
305+
306+function forEach(obj, iterator, context) {
307+ var key, length;
308+ if (obj) {
309+ if (isFunction(obj)) {
310+ for (key in obj) {
311+ // Need to check if hasOwnProperty exists,
312+ // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
313+ if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
314+ iterator.call(context, obj[key], key, obj);
315+ }
316+ }
317+ } else if (isArray(obj) || isArrayLike(obj)) {
318+ var isPrimitive = typeof obj !== 'object';
319+ for (key = 0, length = obj.length; key < length; key++) {
320+ if (isPrimitive || key in obj) {
321+ iterator.call(context, obj[key], key, obj);
322+ }
323+ }
324+ } else if (obj.forEach && obj.forEach !== forEach) {
325+ obj.forEach(iterator, context, obj);
326+ } else if (isBlankObject(obj)) {
327+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
328+ for (key in obj) {
329+ iterator.call(context, obj[key], key, obj);
330+ }
331+ } else if (typeof obj.hasOwnProperty === 'function') {
332+ // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
333+ for (key in obj) {
334+ if (obj.hasOwnProperty(key)) {
335+ iterator.call(context, obj[key], key, obj);
336+ }
337+ }
338+ } else {
339+ // Slow path for objects which do not have a method `hasOwnProperty`
340+ for (key in obj) {
341+ if (hasOwnProperty.call(obj, key)) {
342+ iterator.call(context, obj[key], key, obj);
343+ }
344+ }
345+ }
346+ }
347+ return obj;
348+}
349+
350+function forEachSorted(obj, iterator, context) {
351+ var keys = Object.keys(obj).sort();
352+ for (var i = 0; i < keys.length; i++) {
353+ iterator.call(context, obj[keys[i]], keys[i]);
354+ }
355+ return keys;
356+}
357+
358+
359+/**
360+ * when using forEach the params are value, key, but it is often useful to have key, value.
361+ * @param {function(string, *)} iteratorFn
362+ * @returns {function(*, string)}
363+ */
364+function reverseParams(iteratorFn) {
365+ return function(value, key) {iteratorFn(key, value);};
366+}
367+
368+/**
369+ * A consistent way of creating unique IDs in angular.
370+ *
371+ * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
372+ * we hit number precision issues in JavaScript.
373+ *
374+ * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
375+ *
376+ * @returns {number} an unique alpha-numeric string
377+ */
378+function nextUid() {
379+ return ++uid;
380+}
381+
382+
383+/**
384+ * Set or clear the hashkey for an object.
385+ * @param obj object
386+ * @param h the hashkey (!truthy to delete the hashkey)
387+ */
388+function setHashKey(obj, h) {
389+ if (h) {
390+ obj.$$hashKey = h;
391+ } else {
392+ delete obj.$$hashKey;
393+ }
394+}
395+
396+
397+function baseExtend(dst, objs, deep) {
398+ var h = dst.$$hashKey;
399+
400+ for (var i = 0, ii = objs.length; i < ii; ++i) {
401+ var obj = objs[i];
402+ if (!isObject(obj) && !isFunction(obj)) continue;
403+ var keys = Object.keys(obj);
404+ for (var j = 0, jj = keys.length; j < jj; j++) {
405+ var key = keys[j];
406+ var src = obj[key];
407+
408+ if (deep && isObject(src)) {
409+ if (isDate(src)) {
410+ dst[key] = new Date(src.valueOf());
411+ } else if (isRegExp(src)) {
412+ dst[key] = new RegExp(src);
413+ } else if (src.nodeName) {
414+ dst[key] = src.cloneNode(true);
415+ } else if (isElement(src)) {
416+ dst[key] = src.clone();
417+ } else {
418+ if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
419+ baseExtend(dst[key], [src], true);
420+ }
421+ } else {
422+ dst[key] = src;
423+ }
424+ }
425+ }
426+
427+ setHashKey(dst, h);
428+ return dst;
429+}
430+
431+/**
432+ * @ngdoc function
433+ * @name angular.extend
434+ * @module ng
435+ * @kind function
436+ *
437+ * @description
438+ * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
439+ * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
440+ * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
441+ *
442+ * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
443+ * {@link angular.merge} for this.
444+ *
445+ * @param {Object} dst Destination object.
446+ * @param {...Object} src Source object(s).
447+ * @returns {Object} Reference to `dst`.
448+ */
449+function extend(dst) {
450+ return baseExtend(dst, slice.call(arguments, 1), false);
451+}
452+
453+
454+/**
455+* @ngdoc function
456+* @name angular.merge
457+* @module ng
458+* @kind function
459+*
460+* @description
461+* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
462+* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
463+* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
464+*
465+* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
466+* objects, performing a deep copy.
467+*
468+* @param {Object} dst Destination object.
469+* @param {...Object} src Source object(s).
470+* @returns {Object} Reference to `dst`.
471+*/
472+function merge(dst) {
473+ return baseExtend(dst, slice.call(arguments, 1), true);
474+}
475+
476+
477+
478+function toInt(str) {
479+ return parseInt(str, 10);
480+}
481+
482+
483+function inherit(parent, extra) {
484+ return extend(Object.create(parent), extra);
485+}
486+
487+/**
488+ * @ngdoc function
489+ * @name angular.noop
490+ * @module ng
491+ * @kind function
492+ *
493+ * @description
494+ * A function that performs no operations. This function can be useful when writing code in the
495+ * functional style.
496+ ```js
497+ function foo(callback) {
498+ var result = calculateResult();
499+ (callback || angular.noop)(result);
500+ }
501+ ```
502+ */
503+function noop() {}
504+noop.$inject = [];
505+
506+
507+/**
508+ * @ngdoc function
509+ * @name angular.identity
510+ * @module ng
511+ * @kind function
512+ *
513+ * @description
514+ * A function that returns its first argument. This function is useful when writing code in the
515+ * functional style.
516+ *
517+ ```js
518+ function transformer(transformationFn, value) {
519+ return (transformationFn || angular.identity)(value);
520+ };
521+
522+ // E.g.
523+ function getResult(fn, input) {
524+ return (fn || angular.identity)(input);
525+ };
526+
527+ getResult(function(n) { return n * 2; }, 21); // returns 42
528+ getResult(null, 21); // returns 21
529+ getResult(undefined, 21); // returns 21
530+ ```
531+ *
532+ * @param {*} value to be returned.
533+ * @returns {*} the value passed in.
534+ */
535+function identity($) {return $;}
536+identity.$inject = [];
537+
538+
539+function valueFn(value) {return function valueRef() {return value;};}
540+
541+function hasCustomToString(obj) {
542+ return isFunction(obj.toString) && obj.toString !== toString;
543+}
544+
545+
546+/**
547+ * @ngdoc function
548+ * @name angular.isUndefined
549+ * @module ng
550+ * @kind function
551+ *
552+ * @description
553+ * Determines if a reference is undefined.
554+ *
555+ * @param {*} value Reference to check.
556+ * @returns {boolean} True if `value` is undefined.
557+ */
558+function isUndefined(value) {return typeof value === 'undefined';}
559+
560+
561+/**
562+ * @ngdoc function
563+ * @name angular.isDefined
564+ * @module ng
565+ * @kind function
566+ *
567+ * @description
568+ * Determines if a reference is defined.
569+ *
570+ * @param {*} value Reference to check.
571+ * @returns {boolean} True if `value` is defined.
572+ */
573+function isDefined(value) {return typeof value !== 'undefined';}
574+
575+
576+/**
577+ * @ngdoc function
578+ * @name angular.isObject
579+ * @module ng
580+ * @kind function
581+ *
582+ * @description
583+ * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
584+ * considered to be objects. Note that JavaScript arrays are objects.
585+ *
586+ * @param {*} value Reference to check.
587+ * @returns {boolean} True if `value` is an `Object` but not `null`.
588+ */
589+function isObject(value) {
590+ // http://jsperf.com/isobject4
591+ return value !== null && typeof value === 'object';
592+}
593+
594+
595+/**
596+ * Determine if a value is an object with a null prototype
597+ *
598+ * @returns {boolean} True if `value` is an `Object` with a null prototype
599+ */
600+function isBlankObject(value) {
601+ return value !== null && typeof value === 'object' && !getPrototypeOf(value);
602+}
603+
604+
605+/**
606+ * @ngdoc function
607+ * @name angular.isString
608+ * @module ng
609+ * @kind function
610+ *
611+ * @description
612+ * Determines if a reference is a `String`.
613+ *
614+ * @param {*} value Reference to check.
615+ * @returns {boolean} True if `value` is a `String`.
616+ */
617+function isString(value) {return typeof value === 'string';}
618+
619+
620+/**
621+ * @ngdoc function
622+ * @name angular.isNumber
623+ * @module ng
624+ * @kind function
625+ *
626+ * @description
627+ * Determines if a reference is a `Number`.
628+ *
629+ * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
630+ *
631+ * If you wish to exclude these then you can use the native
632+ * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
633+ * method.
634+ *
635+ * @param {*} value Reference to check.
636+ * @returns {boolean} True if `value` is a `Number`.
637+ */
638+function isNumber(value) {return typeof value === 'number';}
639+
640+
641+/**
642+ * @ngdoc function
643+ * @name angular.isDate
644+ * @module ng
645+ * @kind function
646+ *
647+ * @description
648+ * Determines if a value is a date.
649+ *
650+ * @param {*} value Reference to check.
651+ * @returns {boolean} True if `value` is a `Date`.
652+ */
653+function isDate(value) {
654+ return toString.call(value) === '[object Date]';
655+}
656+
657+
658+/**
659+ * @ngdoc function
660+ * @name angular.isArray
661+ * @module ng
662+ * @kind function
663+ *
664+ * @description
665+ * Determines if a reference is an `Array`.
666+ *
667+ * @param {*} value Reference to check.
668+ * @returns {boolean} True if `value` is an `Array`.
669+ */
670+var isArray = Array.isArray;
671+
672+/**
673+ * @ngdoc function
674+ * @name angular.isFunction
675+ * @module ng
676+ * @kind function
677+ *
678+ * @description
679+ * Determines if a reference is a `Function`.
680+ *
681+ * @param {*} value Reference to check.
682+ * @returns {boolean} True if `value` is a `Function`.
683+ */
684+function isFunction(value) {return typeof value === 'function';}
685+
686+
687+/**
688+ * Determines if a value is a regular expression object.
689+ *
690+ * @private
691+ * @param {*} value Reference to check.
692+ * @returns {boolean} True if `value` is a `RegExp`.
693+ */
694+function isRegExp(value) {
695+ return toString.call(value) === '[object RegExp]';
696+}
697+
698+
699+/**
700+ * Checks if `obj` is a window object.
701+ *
702+ * @private
703+ * @param {*} obj Object to check
704+ * @returns {boolean} True if `obj` is a window obj.
705+ */
706+function isWindow(obj) {
707+ return obj && obj.window === obj;
708+}
709+
710+
711+function isScope(obj) {
712+ return obj && obj.$evalAsync && obj.$watch;
713+}
714+
715+
716+function isFile(obj) {
717+ return toString.call(obj) === '[object File]';
718+}
719+
720+
721+function isFormData(obj) {
722+ return toString.call(obj) === '[object FormData]';
723+}
724+
725+
726+function isBlob(obj) {
727+ return toString.call(obj) === '[object Blob]';
728+}
729+
730+
731+function isBoolean(value) {
732+ return typeof value === 'boolean';
733+}
734+
735+
736+function isPromiseLike(obj) {
737+ return obj && isFunction(obj.then);
738+}
739+
740+
741+var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
742+function isTypedArray(value) {
743+ return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
744+}
745+
746+function isArrayBuffer(obj) {
747+ return toString.call(obj) === '[object ArrayBuffer]';
748+}
749+
750+
751+var trim = function(value) {
752+ return isString(value) ? value.trim() : value;
753+};
754+
755+// Copied from:
756+// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
757+// Prereq: s is a string.
758+var escapeForRegexp = function(s) {
759+ return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
760+ replace(/\x08/g, '\\x08');
761+};
762+
763+
764+/**
765+ * @ngdoc function
766+ * @name angular.isElement
767+ * @module ng
768+ * @kind function
769+ *
770+ * @description
771+ * Determines if a reference is a DOM element (or wrapped jQuery element).
772+ *
773+ * @param {*} value Reference to check.
774+ * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
775+ */
776+function isElement(node) {
777+ return !!(node &&
778+ (node.nodeName // We are a direct element.
779+ || (node.prop && node.attr && node.find))); // We have an on and find method part of jQuery API.
780+}
781+
782+/**
783+ * @param str 'key1,key2,...'
784+ * @returns {object} in the form of {key1:true, key2:true, ...}
785+ */
786+function makeMap(str) {
787+ var obj = {}, items = str.split(','), i;
788+ for (i = 0; i < items.length; i++) {
789+ obj[items[i]] = true;
790+ }
791+ return obj;
792+}
793+
794+
795+function nodeName_(element) {
796+ return lowercase(element.nodeName || (element[0] && element[0].nodeName));
797+}
798+
799+function includes(array, obj) {
800+ return Array.prototype.indexOf.call(array, obj) != -1;
801+}
802+
803+function arrayRemove(array, value) {
804+ var index = array.indexOf(value);
805+ if (index >= 0) {
806+ array.splice(index, 1);
807+ }
808+ return index;
809+}
810+
811+/**
812+ * @ngdoc function
813+ * @name angular.copy
814+ * @module ng
815+ * @kind function
816+ *
817+ * @description
818+ * Creates a deep copy of `source`, which should be an object or an array.
819+ *
820+ * * If no destination is supplied, a copy of the object or array is created.
821+ * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
822+ * are deleted and then all elements/properties from the source are copied to it.
823+ * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
824+ * * If `source` is identical to `destination` an exception will be thrown.
825+ *
826+ * <br />
827+ * <div class="alert alert-warning">
828+ * Only enumerable properties are taken into account. Non-enumerable properties (both on `source`
829+ * and on `destination`) will be ignored.
830+ * </div>
831+ *
832+ * @param {*} source The source that will be used to make a copy.
833+ * Can be any type, including primitives, `null`, and `undefined`.
834+ * @param {(Object|Array)=} destination Destination into which the source is copied. If
835+ * provided, must be of the same type as `source`.
836+ * @returns {*} The copy or updated `destination`, if `destination` was specified.
837+ *
838+ * @example
839+ <example module="copyExample">
840+ <file name="index.html">
841+ <div ng-controller="ExampleController">
842+ <form novalidate class="simple-form">
843+ <label>Name: <input type="text" ng-model="user.name" /></label><br />
844+ <label>Age: <input type="number" ng-model="user.age" /></label><br />
845+ Gender: <label><input type="radio" ng-model="user.gender" value="male" />male</label>
846+ <label><input type="radio" ng-model="user.gender" value="female" />female</label><br />
847+ <button ng-click="reset()">RESET</button>
848+ <button ng-click="update(user)">SAVE</button>
849+ </form>
850+ <pre>form = {{user | json}}</pre>
851+ <pre>master = {{master | json}}</pre>
852+ </div>
853+ </file>
854+ <file name="script.js">
855+ // Module: copyExample
856+ angular.
857+ module('copyExample', []).
858+ controller('ExampleController', ['$scope', function($scope) {
859+ $scope.master = {};
860+
861+ $scope.reset = function() {
862+ // Example with 1 argument
863+ $scope.user = angular.copy($scope.master);
864+ };
865+
866+ $scope.update = function(user) {
867+ // Example with 2 arguments
868+ angular.copy(user, $scope.master);
869+ };
870+
871+ $scope.reset();
872+ }]);
873+ </file>
874+ </example>
875+ */
876+function copy(source, destination) {
877+ var stackSource = [];
878+ var stackDest = [];
879+
880+ if (destination) {
881+ if (isTypedArray(destination) || isArrayBuffer(destination)) {
882+ throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
883+ }
884+ if (source === destination) {
885+ throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
886+ }
887+
888+ // Empty the destination object
889+ if (isArray(destination)) {
890+ destination.length = 0;
891+ } else {
892+ forEach(destination, function(value, key) {
893+ if (key !== '$$hashKey') {
894+ delete destination[key];
895+ }
896+ });
897+ }
898+
899+ stackSource.push(source);
900+ stackDest.push(destination);
901+ return copyRecurse(source, destination);
902+ }
903+
904+ return copyElement(source);
905+
906+ function copyRecurse(source, destination) {
907+ var h = destination.$$hashKey;
908+ var key;
909+ if (isArray(source)) {
910+ for (var i = 0, ii = source.length; i < ii; i++) {
911+ destination.push(copyElement(source[i]));
912+ }
913+ } else if (isBlankObject(source)) {
914+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
915+ for (key in source) {
916+ destination[key] = copyElement(source[key]);
917+ }
918+ } else if (source && typeof source.hasOwnProperty === 'function') {
919+ // Slow path, which must rely on hasOwnProperty
920+ for (key in source) {
921+ if (source.hasOwnProperty(key)) {
922+ destination[key] = copyElement(source[key]);
923+ }
924+ }
925+ } else {
926+ // Slowest path --- hasOwnProperty can't be called as a method
927+ for (key in source) {
928+ if (hasOwnProperty.call(source, key)) {
929+ destination[key] = copyElement(source[key]);
930+ }
931+ }
932+ }
933+ setHashKey(destination, h);
934+ return destination;
935+ }
936+
937+ function copyElement(source) {
938+ // Simple values
939+ if (!isObject(source)) {
940+ return source;
941+ }
942+
943+ // Already copied values
944+ var index = stackSource.indexOf(source);
945+ if (index !== -1) {
946+ return stackDest[index];
947+ }
948+
949+ if (isWindow(source) || isScope(source)) {
950+ throw ngMinErr('cpws',
951+ "Can't copy! Making copies of Window or Scope instances is not supported.");
952+ }
953+
954+ var needsRecurse = false;
955+ var destination = copyType(source);
956+
957+ if (destination === undefined) {
958+ destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
959+ needsRecurse = true;
960+ }
961+
962+ stackSource.push(source);
963+ stackDest.push(destination);
964+
965+ return needsRecurse
966+ ? copyRecurse(source, destination)
967+ : destination;
968+ }
969+
970+ function copyType(source) {
971+ switch (toString.call(source)) {
972+ case '[object Int8Array]':
973+ case '[object Int16Array]':
974+ case '[object Int32Array]':
975+ case '[object Float32Array]':
976+ case '[object Float64Array]':
977+ case '[object Uint8Array]':
978+ case '[object Uint8ClampedArray]':
979+ case '[object Uint16Array]':
980+ case '[object Uint32Array]':
981+ return new source.constructor(copyElement(source.buffer), source.byteOffset, source.length);
982+
983+ case '[object ArrayBuffer]':
984+ //Support: IE10
985+ if (!source.slice) {
986+ var copied = new ArrayBuffer(source.byteLength);
987+ new Uint8Array(copied).set(new Uint8Array(source));
988+ return copied;
989+ }
990+ return source.slice(0);
991+
992+ case '[object Boolean]':
993+ case '[object Number]':
994+ case '[object String]':
995+ case '[object Date]':
996+ return new source.constructor(source.valueOf());
997+
998+ case '[object RegExp]':
999+ var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
1000+ re.lastIndex = source.lastIndex;
1001+ return re;
1002+
1003+ case '[object Blob]':
1004+ return new source.constructor([source], {type: source.type});
1005+ }
1006+
1007+ if (isFunction(source.cloneNode)) {
1008+ return source.cloneNode(true);
1009+ }
1010+ }
1011+}
1012+
1013+
1014+/**
1015+ * @ngdoc function
1016+ * @name angular.equals
1017+ * @module ng
1018+ * @kind function
1019+ *
1020+ * @description
1021+ * Determines if two objects or two values are equivalent. Supports value types, regular
1022+ * expressions, arrays and objects.
1023+ *
1024+ * Two objects or values are considered equivalent if at least one of the following is true:
1025+ *
1026+ * * Both objects or values pass `===` comparison.
1027+ * * Both objects or values are of the same type and all of their properties are equal by
1028+ * comparing them with `angular.equals`.
1029+ * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
1030+ * * Both values represent the same regular expression (In JavaScript,
1031+ * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
1032+ * representation matches).
1033+ *
1034+ * During a property comparison, properties of `function` type and properties with names
1035+ * that begin with `$` are ignored.
1036+ *
1037+ * Scope and DOMWindow objects are being compared only by identify (`===`).
1038+ *
1039+ * @param {*} o1 Object or value to compare.
1040+ * @param {*} o2 Object or value to compare.
1041+ * @returns {boolean} True if arguments are equal.
1042+ *
1043+ * @example
1044+ <example module="equalsExample" name="equalsExample">
1045+ <file name="index.html">
1046+ <div ng-controller="ExampleController">
1047+ <form novalidate>
1048+ <h3>User 1</h3>
1049+ Name: <input type="text" ng-model="user1.name">
1050+ Age: <input type="number" ng-model="user1.age">
1051+
1052+ <h3>User 2</h3>
1053+ Name: <input type="text" ng-model="user2.name">
1054+ Age: <input type="number" ng-model="user2.age">
1055+
1056+ <div>
1057+ <br/>
1058+ <input type="button" value="Compare" ng-click="compare()">
1059+ </div>
1060+ User 1: <pre>{{user1 | json}}</pre>
1061+ User 2: <pre>{{user2 | json}}</pre>
1062+ Equal: <pre>{{result}}</pre>
1063+ </form>
1064+ </div>
1065+ </file>
1066+ <file name="script.js">
1067+ angular.module('equalsExample', []).controller('ExampleController', ['$scope', function($scope) {
1068+ $scope.user1 = {};
1069+ $scope.user2 = {};
1070+ $scope.result;
1071+ $scope.compare = function() {
1072+ $scope.result = angular.equals($scope.user1, $scope.user2);
1073+ };
1074+ }]);
1075+ </file>
1076+ </example>
1077+ */
1078+function equals(o1, o2) {
1079+ if (o1 === o2) return true;
1080+ if (o1 === null || o2 === null) return false;
1081+ if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
1082+ var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
1083+ if (t1 == t2 && t1 == 'object') {
1084+ if (isArray(o1)) {
1085+ if (!isArray(o2)) return false;
1086+ if ((length = o1.length) == o2.length) {
1087+ for (key = 0; key < length; key++) {
1088+ if (!equals(o1[key], o2[key])) return false;
1089+ }
1090+ return true;
1091+ }
1092+ } else if (isDate(o1)) {
1093+ if (!isDate(o2)) return false;
1094+ return equals(o1.getTime(), o2.getTime());
1095+ } else if (isRegExp(o1)) {
1096+ if (!isRegExp(o2)) return false;
1097+ return o1.toString() == o2.toString();
1098+ } else {
1099+ if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
1100+ isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
1101+ keySet = createMap();
1102+ for (key in o1) {
1103+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
1104+ if (!equals(o1[key], o2[key])) return false;
1105+ keySet[key] = true;
1106+ }
1107+ for (key in o2) {
1108+ if (!(key in keySet) &&
1109+ key.charAt(0) !== '$' &&
1110+ isDefined(o2[key]) &&
1111+ !isFunction(o2[key])) return false;
1112+ }
1113+ return true;
1114+ }
1115+ }
1116+ return false;
1117+}
1118+
1119+var csp = function() {
1120+ if (!isDefined(csp.rules)) {
1121+
1122+
1123+ var ngCspElement = (window.document.querySelector('[ng-csp]') ||
1124+ window.document.querySelector('[data-ng-csp]'));
1125+
1126+ if (ngCspElement) {
1127+ var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
1128+ ngCspElement.getAttribute('data-ng-csp');
1129+ csp.rules = {
1130+ noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),
1131+ noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)
1132+ };
1133+ } else {
1134+ csp.rules = {
1135+ noUnsafeEval: noUnsafeEval(),
1136+ noInlineStyle: false
1137+ };
1138+ }
1139+ }
1140+
1141+ return csp.rules;
1142+
1143+ function noUnsafeEval() {
1144+ try {
1145+ /* jshint -W031, -W054 */
1146+ new Function('');
1147+ /* jshint +W031, +W054 */
1148+ return false;
1149+ } catch (e) {
1150+ return true;
1151+ }
1152+ }
1153+};
1154+
1155+/**
1156+ * @ngdoc directive
1157+ * @module ng
1158+ * @name ngJq
1159+ *
1160+ * @element ANY
1161+ * @param {string=} ngJq the name of the library available under `window`
1162+ * to be used for angular.element
1163+ * @description
1164+ * Use this directive to force the angular.element library. This should be
1165+ * used to force either jqLite by leaving ng-jq blank or setting the name of
1166+ * the jquery variable under window (eg. jQuery).
1167+ *
1168+ * Since angular looks for this directive when it is loaded (doesn't wait for the
1169+ * DOMContentLoaded event), it must be placed on an element that comes before the script
1170+ * which loads angular. Also, only the first instance of `ng-jq` will be used and all
1171+ * others ignored.
1172+ *
1173+ * @example
1174+ * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
1175+ ```html
1176+ <!doctype html>
1177+ <html ng-app ng-jq>
1178+ ...
1179+ ...
1180+ </html>
1181+ ```
1182+ * @example
1183+ * This example shows how to use a jQuery based library of a different name.
1184+ * The library name must be available at the top most 'window'.
1185+ ```html
1186+ <!doctype html>
1187+ <html ng-app ng-jq="jQueryLib">
1188+ ...
1189+ ...
1190+ </html>
1191+ ```
1192+ */
1193+var jq = function() {
1194+ if (isDefined(jq.name_)) return jq.name_;
1195+ var el;
1196+ var i, ii = ngAttrPrefixes.length, prefix, name;
1197+ for (i = 0; i < ii; ++i) {
1198+ prefix = ngAttrPrefixes[i];
1199+ if (el = window.document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
1200+ name = el.getAttribute(prefix + 'jq');
1201+ break;
1202+ }
1203+ }
1204+
1205+ return (jq.name_ = name);
1206+};
1207+
1208+function concat(array1, array2, index) {
1209+ return array1.concat(slice.call(array2, index));
1210+}
1211+
1212+function sliceArgs(args, startIndex) {
1213+ return slice.call(args, startIndex || 0);
1214+}
1215+
1216+
1217+/* jshint -W101 */
1218+/**
1219+ * @ngdoc function
1220+ * @name angular.bind
1221+ * @module ng
1222+ * @kind function
1223+ *
1224+ * @description
1225+ * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
1226+ * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
1227+ * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
1228+ * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
1229+ *
1230+ * @param {Object} self Context which `fn` should be evaluated in.
1231+ * @param {function()} fn Function to be bound.
1232+ * @param {...*} args Optional arguments to be prebound to the `fn` function call.
1233+ * @returns {function()} Function that wraps the `fn` with all the specified bindings.
1234+ */
1235+/* jshint +W101 */
1236+function bind(self, fn) {
1237+ var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
1238+ if (isFunction(fn) && !(fn instanceof RegExp)) {
1239+ return curryArgs.length
1240+ ? function() {
1241+ return arguments.length
1242+ ? fn.apply(self, concat(curryArgs, arguments, 0))
1243+ : fn.apply(self, curryArgs);
1244+ }
1245+ : function() {
1246+ return arguments.length
1247+ ? fn.apply(self, arguments)
1248+ : fn.call(self);
1249+ };
1250+ } else {
1251+ // In IE, native methods are not functions so they cannot be bound (note: they don't need to be).
1252+ return fn;
1253+ }
1254+}
1255+
1256+
1257+function toJsonReplacer(key, value) {
1258+ var val = value;
1259+
1260+ if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
1261+ val = undefined;
1262+ } else if (isWindow(value)) {
1263+ val = '$WINDOW';
1264+ } else if (value && window.document === value) {
1265+ val = '$DOCUMENT';
1266+ } else if (isScope(value)) {
1267+ val = '$SCOPE';
1268+ }
1269+
1270+ return val;
1271+}
1272+
1273+
1274+/**
1275+ * @ngdoc function
1276+ * @name angular.toJson
1277+ * @module ng
1278+ * @kind function
1279+ *
1280+ * @description
1281+ * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
1282+ * stripped since angular uses this notation internally.
1283+ *
1284+ * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
1285+ * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
1286+ * If set to an integer, the JSON output will contain that many spaces per indentation.
1287+ * @returns {string|undefined} JSON-ified string representing `obj`.
1288+ * @knownIssue
1289+ *
1290+ * The Safari browser throws a `RangeError` instead of returning `null` when it tries to stringify a `Date`
1291+ * object with an invalid date value. The only reliable way to prevent this is to monkeypatch the
1292+ * `Date.prototype.toJSON` method as follows:
1293+ *
1294+ * ```
1295+ * var _DatetoJSON = Date.prototype.toJSON;
1296+ * Date.prototype.toJSON = function() {
1297+ * try {
1298+ * return _DatetoJSON.call(this);
1299+ * } catch(e) {
1300+ * if (e instanceof RangeError) {
1301+ * return null;
1302+ * }
1303+ * throw e;
1304+ * }
1305+ * };
1306+ * ```
1307+ *
1308+ * See https://github.com/angular/angular.js/pull/14221 for more information.
1309+ */
1310+function toJson(obj, pretty) {
1311+ if (isUndefined(obj)) return undefined;
1312+ if (!isNumber(pretty)) {
1313+ pretty = pretty ? 2 : null;
1314+ }
1315+ return JSON.stringify(obj, toJsonReplacer, pretty);
1316+}
1317+
1318+
1319+/**
1320+ * @ngdoc function
1321+ * @name angular.fromJson
1322+ * @module ng
1323+ * @kind function
1324+ *
1325+ * @description
1326+ * Deserializes a JSON string.
1327+ *
1328+ * @param {string} json JSON string to deserialize.
1329+ * @returns {Object|Array|string|number} Deserialized JSON string.
1330+ */
1331+function fromJson(json) {
1332+ return isString(json)
1333+ ? JSON.parse(json)
1334+ : json;
1335+}
1336+
1337+
1338+var ALL_COLONS = /:/g;
1339+function timezoneToOffset(timezone, fallback) {
1340+ // IE/Edge do not "understand" colon (`:`) in timezone
1341+ timezone = timezone.replace(ALL_COLONS, '');
1342+ var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
1343+ return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
1344+}
1345+
1346+
1347+function addDateMinutes(date, minutes) {
1348+ date = new Date(date.getTime());
1349+ date.setMinutes(date.getMinutes() + minutes);
1350+ return date;
1351+}
1352+
1353+
1354+function convertTimezoneToLocal(date, timezone, reverse) {
1355+ reverse = reverse ? -1 : 1;
1356+ var dateTimezoneOffset = date.getTimezoneOffset();
1357+ var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
1358+ return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
1359+}
1360+
1361+
1362+/**
1363+ * @returns {string} Returns the string representation of the element.
1364+ */
1365+function startingTag(element) {
1366+ element = jqLite(element).clone();
1367+ try {
1368+ // turns out IE does not let you set .html() on elements which
1369+ // are not allowed to have children. So we just ignore it.
1370+ element.empty();
1371+ } catch (e) {}
1372+ var elemHtml = jqLite('<div>').append(element).html();
1373+ try {
1374+ return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
1375+ elemHtml.
1376+ match(/^(<[^>]+>)/)[1].
1377+ replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);});
1378+ } catch (e) {
1379+ return lowercase(elemHtml);
1380+ }
1381+
1382+}
1383+
1384+
1385+/////////////////////////////////////////////////
1386+
1387+/**
1388+ * Tries to decode the URI component without throwing an exception.
1389+ *
1390+ * @private
1391+ * @param str value potential URI component to check.
1392+ * @returns {boolean} True if `value` can be decoded
1393+ * with the decodeURIComponent function.
1394+ */
1395+function tryDecodeURIComponent(value) {
1396+ try {
1397+ return decodeURIComponent(value);
1398+ } catch (e) {
1399+ // Ignore any invalid uri component.
1400+ }
1401+}
1402+
1403+
1404+/**
1405+ * Parses an escaped url query string into key-value pairs.
1406+ * @returns {Object.<string,boolean|Array>}
1407+ */
1408+function parseKeyValue(/**string*/keyValue) {
1409+ var obj = {};
1410+ forEach((keyValue || "").split('&'), function(keyValue) {
1411+ var splitPoint, key, val;
1412+ if (keyValue) {
1413+ key = keyValue = keyValue.replace(/\+/g,'%20');
1414+ splitPoint = keyValue.indexOf('=');
1415+ if (splitPoint !== -1) {
1416+ key = keyValue.substring(0, splitPoint);
1417+ val = keyValue.substring(splitPoint + 1);
1418+ }
1419+ key = tryDecodeURIComponent(key);
1420+ if (isDefined(key)) {
1421+ val = isDefined(val) ? tryDecodeURIComponent(val) : true;
1422+ if (!hasOwnProperty.call(obj, key)) {
1423+ obj[key] = val;
1424+ } else if (isArray(obj[key])) {
1425+ obj[key].push(val);
1426+ } else {
1427+ obj[key] = [obj[key],val];
1428+ }
1429+ }
1430+ }
1431+ });
1432+ return obj;
1433+}
1434+
1435+function toKeyValue(obj) {
1436+ var parts = [];
1437+ forEach(obj, function(value, key) {
1438+ if (isArray(value)) {
1439+ forEach(value, function(arrayValue) {
1440+ parts.push(encodeUriQuery(key, true) +
1441+ (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
1442+ });
1443+ } else {
1444+ parts.push(encodeUriQuery(key, true) +
1445+ (value === true ? '' : '=' + encodeUriQuery(value, true)));
1446+ }
1447+ });
1448+ return parts.length ? parts.join('&') : '';
1449+}
1450+
1451+
1452+/**
1453+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
1454+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
1455+ * segments:
1456+ * segment = *pchar
1457+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
1458+ * pct-encoded = "%" HEXDIG HEXDIG
1459+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1460+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1461+ * / "*" / "+" / "," / ";" / "="
1462+ */
1463+function encodeUriSegment(val) {
1464+ return encodeUriQuery(val, true).
1465+ replace(/%26/gi, '&').
1466+ replace(/%3D/gi, '=').
1467+ replace(/%2B/gi, '+');
1468+}
1469+
1470+
1471+/**
1472+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
1473+ * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
1474+ * encoded per http://tools.ietf.org/html/rfc3986:
1475+ * query = *( pchar / "/" / "?" )
1476+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
1477+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1478+ * pct-encoded = "%" HEXDIG HEXDIG
1479+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1480+ * / "*" / "+" / "," / ";" / "="
1481+ */
1482+function encodeUriQuery(val, pctEncodeSpaces) {
1483+ return encodeURIComponent(val).
1484+ replace(/%40/gi, '@').
1485+ replace(/%3A/gi, ':').
1486+ replace(/%24/g, '$').
1487+ replace(/%2C/gi, ',').
1488+ replace(/%3B/gi, ';').
1489+ replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
1490+}
1491+
1492+var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
1493+
1494+function getNgAttribute(element, ngAttr) {
1495+ var attr, i, ii = ngAttrPrefixes.length;
1496+ for (i = 0; i < ii; ++i) {
1497+ attr = ngAttrPrefixes[i] + ngAttr;
1498+ if (isString(attr = element.getAttribute(attr))) {
1499+ return attr;
1500+ }
1501+ }
1502+ return null;
1503+}
1504+
1505+/**
1506+ * @ngdoc directive
1507+ * @name ngApp
1508+ * @module ng
1509+ *
1510+ * @element ANY
1511+ * @param {angular.Module} ngApp an optional application
1512+ * {@link angular.module module} name to load.
1513+ * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
1514+ * created in "strict-di" mode. This means that the application will fail to invoke functions which
1515+ * do not use explicit function annotation (and are thus unsuitable for minification), as described
1516+ * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
1517+ * tracking down the root of these bugs.
1518+ *
1519+ * @description
1520+ *
1521+ * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
1522+ * designates the **root element** of the application and is typically placed near the root element
1523+ * of the page - e.g. on the `<body>` or `<html>` tags.
1524+ *
1525+ * There are a few things to keep in mind when using `ngApp`:
1526+ * - only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
1527+ * found in the document will be used to define the root element to auto-bootstrap as an
1528+ * application. To run multiple applications in an HTML document you must manually bootstrap them using
1529+ * {@link angular.bootstrap} instead.
1530+ * - AngularJS applications cannot be nested within each other.
1531+ * - Do not use a directive that uses {@link ng.$compile#transclusion transclusion} on the same element as `ngApp`.
1532+ * This includes directives such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and
1533+ * {@link ngRoute.ngView `ngView`}.
1534+ * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector},
1535+ * causing animations to stop working and making the injector inaccessible from outside the app.
1536+ *
1537+ * You can specify an **AngularJS module** to be used as the root module for the application. This
1538+ * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
1539+ * should contain the application code needed or have dependencies on other modules that will
1540+ * contain the code. See {@link angular.module} for more information.
1541+ *
1542+ * In the example below if the `ngApp` directive were not placed on the `html` element then the
1543+ * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
1544+ * would not be resolved to `3`.
1545+ *
1546+ * `ngApp` is the easiest, and most common way to bootstrap an application.
1547+ *
1548+ <example module="ngAppDemo">
1549+ <file name="index.html">
1550+ <div ng-controller="ngAppDemoController">
1551+ I can add: {{a}} + {{b}} = {{ a+b }}
1552+ </div>
1553+ </file>
1554+ <file name="script.js">
1555+ angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
1556+ $scope.a = 1;
1557+ $scope.b = 2;
1558+ });
1559+ </file>
1560+ </example>
1561+ *
1562+ * Using `ngStrictDi`, you would see something like this:
1563+ *
1564+ <example ng-app-included="true">
1565+ <file name="index.html">
1566+ <div ng-app="ngAppStrictDemo" ng-strict-di>
1567+ <div ng-controller="GoodController1">
1568+ I can add: {{a}} + {{b}} = {{ a+b }}
1569+
1570+ <p>This renders because the controller does not fail to
1571+ instantiate, by using explicit annotation style (see
1572+ script.js for details)
1573+ </p>
1574+ </div>
1575+
1576+ <div ng-controller="GoodController2">
1577+ Name: <input ng-model="name"><br />
1578+ Hello, {{name}}!
1579+
1580+ <p>This renders because the controller does not fail to
1581+ instantiate, by using explicit annotation style
1582+ (see script.js for details)
1583+ </p>
1584+ </div>
1585+
1586+ <div ng-controller="BadController">
1587+ I can add: {{a}} + {{b}} = {{ a+b }}
1588+
1589+ <p>The controller could not be instantiated, due to relying
1590+ on automatic function annotations (which are disabled in
1591+ strict mode). As such, the content of this section is not
1592+ interpolated, and there should be an error in your web console.
1593+ </p>
1594+ </div>
1595+ </div>
1596+ </file>
1597+ <file name="script.js">
1598+ angular.module('ngAppStrictDemo', [])
1599+ // BadController will fail to instantiate, due to relying on automatic function annotation,
1600+ // rather than an explicit annotation
1601+ .controller('BadController', function($scope) {
1602+ $scope.a = 1;
1603+ $scope.b = 2;
1604+ })
1605+ // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
1606+ // due to using explicit annotations using the array style and $inject property, respectively.
1607+ .controller('GoodController1', ['$scope', function($scope) {
1608+ $scope.a = 1;
1609+ $scope.b = 2;
1610+ }])
1611+ .controller('GoodController2', GoodController2);
1612+ function GoodController2($scope) {
1613+ $scope.name = "World";
1614+ }
1615+ GoodController2.$inject = ['$scope'];
1616+ </file>
1617+ <file name="style.css">
1618+ div[ng-controller] {
1619+ margin-bottom: 1em;
1620+ -webkit-border-radius: 4px;
1621+ border-radius: 4px;
1622+ border: 1px solid;
1623+ padding: .5em;
1624+ }
1625+ div[ng-controller^=Good] {
1626+ border-color: #d6e9c6;
1627+ background-color: #dff0d8;
1628+ color: #3c763d;
1629+ }
1630+ div[ng-controller^=Bad] {
1631+ border-color: #ebccd1;
1632+ background-color: #f2dede;
1633+ color: #a94442;
1634+ margin-bottom: 0;
1635+ }
1636+ </file>
1637+ </example>
1638+ */
1639+function angularInit(element, bootstrap) {
1640+ var appElement,
1641+ module,
1642+ config = {};
1643+
1644+ // The element `element` has priority over any other element.
1645+ forEach(ngAttrPrefixes, function(prefix) {
1646+ var name = prefix + 'app';
1647+
1648+ if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
1649+ appElement = element;
1650+ module = element.getAttribute(name);
1651+ }
1652+ });
1653+ forEach(ngAttrPrefixes, function(prefix) {
1654+ var name = prefix + 'app';
1655+ var candidate;
1656+
1657+ if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
1658+ appElement = candidate;
1659+ module = candidate.getAttribute(name);
1660+ }
1661+ });
1662+ if (appElement) {
1663+ config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
1664+ bootstrap(appElement, module ? [module] : [], config);
1665+ }
1666+}
1667+
1668+/**
1669+ * @ngdoc function
1670+ * @name angular.bootstrap
1671+ * @module ng
1672+ * @description
1673+ * Use this function to manually start up angular application.
1674+ *
1675+ * For more information, see the {@link guide/bootstrap Bootstrap guide}.
1676+ *
1677+ * Angular will detect if it has been loaded into the browser more than once and only allow the
1678+ * first loaded script to be bootstrapped and will report a warning to the browser console for
1679+ * each of the subsequent scripts. This prevents strange results in applications, where otherwise
1680+ * multiple instances of Angular try to work on the DOM.
1681+ *
1682+ * <div class="alert alert-warning">
1683+ * **Note:** Protractor based end-to-end tests cannot use this function to bootstrap manually.
1684+ * They must use {@link ng.directive:ngApp ngApp}.
1685+ * </div>
1686+ *
1687+ * <div class="alert alert-warning">
1688+ * **Note:** Do not bootstrap the app on an element with a directive that uses {@link ng.$compile#transclusion transclusion},
1689+ * such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and {@link ngRoute.ngView `ngView`}.
1690+ * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector},
1691+ * causing animations to stop working and making the injector inaccessible from outside the app.
1692+ * </div>
1693+ *
1694+ * ```html
1695+ * <!doctype html>
1696+ * <html>
1697+ * <body>
1698+ * <div ng-controller="WelcomeController">
1699+ * {{greeting}}
1700+ * </div>
1701+ *
1702+ * <script src="angular.js"></script>
1703+ * <script>
1704+ * var app = angular.module('demo', [])
1705+ * .controller('WelcomeController', function($scope) {
1706+ * $scope.greeting = 'Welcome!';
1707+ * });
1708+ * angular.bootstrap(document, ['demo']);
1709+ * </script>
1710+ * </body>
1711+ * </html>
1712+ * ```
1713+ *
1714+ * @param {DOMElement} element DOM element which is the root of angular application.
1715+ * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
1716+ * Each item in the array should be the name of a predefined module or a (DI annotated)
1717+ * function that will be invoked by the injector as a `config` block.
1718+ * See: {@link angular.module modules}
1719+ * @param {Object=} config an object for defining configuration options for the application. The
1720+ * following keys are supported:
1721+ *
1722+ * * `strictDi` - disable automatic function annotation for the application. This is meant to
1723+ * assist in finding bugs which break minified code. Defaults to `false`.
1724+ *
1725+ * @returns {auto.$injector} Returns the newly created injector for this app.
1726+ */
1727+function bootstrap(element, modules, config) {
1728+ if (!isObject(config)) config = {};
1729+ var defaultConfig = {
1730+ strictDi: false
1731+ };
1732+ config = extend(defaultConfig, config);
1733+ var doBootstrap = function() {
1734+ element = jqLite(element);
1735+
1736+ if (element.injector()) {
1737+ var tag = (element[0] === window.document) ? 'document' : startingTag(element);
1738+ // Encode angle brackets to prevent input from being sanitized to empty string #8683.
1739+ throw ngMinErr(
1740+ 'btstrpd',
1741+ "App already bootstrapped with this element '{0}'",
1742+ tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
1743+ }
1744+
1745+ modules = modules || [];
1746+ modules.unshift(['$provide', function($provide) {
1747+ $provide.value('$rootElement', element);
1748+ }]);
1749+
1750+ if (config.debugInfoEnabled) {
1751+ // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.
1752+ modules.push(['$compileProvider', function($compileProvider) {
1753+ $compileProvider.debugInfoEnabled(true);
1754+ }]);
1755+ }
1756+
1757+ modules.unshift('ng');
1758+ var injector = createInjector(modules, config.strictDi);
1759+ injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
1760+ function bootstrapApply(scope, element, compile, injector) {
1761+ scope.$apply(function() {
1762+ element.data('$injector', injector);
1763+ compile(element)(scope);
1764+ });
1765+ }]
1766+ );
1767+ return injector;
1768+ };
1769+
1770+ var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;
1771+ var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
1772+
1773+ if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {
1774+ config.debugInfoEnabled = true;
1775+ window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');
1776+ }
1777+
1778+ if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
1779+ return doBootstrap();
1780+ }
1781+
1782+ window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
1783+ angular.resumeBootstrap = function(extraModules) {
1784+ forEach(extraModules, function(module) {
1785+ modules.push(module);
1786+ });
1787+ return doBootstrap();
1788+ };
1789+
1790+ if (isFunction(angular.resumeDeferredBootstrap)) {
1791+ angular.resumeDeferredBootstrap();
1792+ }
1793+}
1794+
1795+/**
1796+ * @ngdoc function
1797+ * @name angular.reloadWithDebugInfo
1798+ * @module ng
1799+ * @description
1800+ * Use this function to reload the current application with debug information turned on.
1801+ * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.
1802+ *
1803+ * See {@link ng.$compileProvider#debugInfoEnabled} for more.
1804+ */
1805+function reloadWithDebugInfo() {
1806+ window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
1807+ window.location.reload();
1808+}
1809+
1810+/**
1811+ * @name angular.getTestability
1812+ * @module ng
1813+ * @description
1814+ * Get the testability service for the instance of Angular on the given
1815+ * element.
1816+ * @param {DOMElement} element DOM element which is the root of angular application.
1817+ */
1818+function getTestability(rootElement) {
1819+ var injector = angular.element(rootElement).injector();
1820+ if (!injector) {
1821+ throw ngMinErr('test',
1822+ 'no injector found for element argument to getTestability');
1823+ }
1824+ return injector.get('$$testability');
1825+}
1826+
1827+var SNAKE_CASE_REGEXP = /[A-Z]/g;
1828+function snake_case(name, separator) {
1829+ separator = separator || '_';
1830+ return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
1831+ return (pos ? separator : '') + letter.toLowerCase();
1832+ });
1833+}
1834+
1835+var bindJQueryFired = false;
1836+function bindJQuery() {
1837+ var originalCleanData;
1838+
1839+ if (bindJQueryFired) {
1840+ return;
1841+ }
1842+
1843+ // bind to jQuery if present;
1844+ var jqName = jq();
1845+ jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
1846+ !jqName ? undefined : // use jqLite
1847+ window[jqName]; // use jQuery specified by `ngJq`
1848+
1849+ // Use jQuery if it exists with proper functionality, otherwise default to us.
1850+ // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
1851+ // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
1852+ // versions. It will not work for sure with jQuery <1.7, though.
1853+ if (jQuery && jQuery.fn.on) {
1854+ jqLite = jQuery;
1855+ extend(jQuery.fn, {
1856+ scope: JQLitePrototype.scope,
1857+ isolateScope: JQLitePrototype.isolateScope,
1858+ controller: JQLitePrototype.controller,
1859+ injector: JQLitePrototype.injector,
1860+ inheritedData: JQLitePrototype.inheritedData
1861+ });
1862+
1863+ // All nodes removed from the DOM via various jQuery APIs like .remove()
1864+ // are passed through jQuery.cleanData. Monkey-patch this method to fire
1865+ // the $destroy event on all removed nodes.
1866+ originalCleanData = jQuery.cleanData;
1867+ jQuery.cleanData = function(elems) {
1868+ var events;
1869+ for (var i = 0, elem; (elem = elems[i]) != null; i++) {
1870+ events = jQuery._data(elem, "events");
1871+ if (events && events.$destroy) {
1872+ jQuery(elem).triggerHandler('$destroy');
1873+ }
1874+ }
1875+ originalCleanData(elems);
1876+ };
1877+ } else {
1878+ jqLite = JQLite;
1879+ }
1880+
1881+ angular.element = jqLite;
1882+
1883+ // Prevent double-proxying.
1884+ bindJQueryFired = true;
1885+}
1886+
1887+/**
1888+ * throw error if the argument is falsy.
1889+ */
1890+function assertArg(arg, name, reason) {
1891+ if (!arg) {
1892+ throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
1893+ }
1894+ return arg;
1895+}
1896+
1897+function assertArgFn(arg, name, acceptArrayAnnotation) {
1898+ if (acceptArrayAnnotation && isArray(arg)) {
1899+ arg = arg[arg.length - 1];
1900+ }
1901+
1902+ assertArg(isFunction(arg), name, 'not a function, got ' +
1903+ (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
1904+ return arg;
1905+}
1906+
1907+/**
1908+ * throw error if the name given is hasOwnProperty
1909+ * @param {String} name the name to test
1910+ * @param {String} context the context in which the name is used, such as module or directive
1911+ */
1912+function assertNotHasOwnProperty(name, context) {
1913+ if (name === 'hasOwnProperty') {
1914+ throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
1915+ }
1916+}
1917+
1918+/**
1919+ * Return the value accessible from the object by path. Any undefined traversals are ignored
1920+ * @param {Object} obj starting object
1921+ * @param {String} path path to traverse
1922+ * @param {boolean} [bindFnToScope=true]
1923+ * @returns {Object} value as accessible by path
1924+ */
1925+//TODO(misko): this function needs to be removed
1926+function getter(obj, path, bindFnToScope) {
1927+ if (!path) return obj;
1928+ var keys = path.split('.');
1929+ var key;
1930+ var lastInstance = obj;
1931+ var len = keys.length;
1932+
1933+ for (var i = 0; i < len; i++) {
1934+ key = keys[i];
1935+ if (obj) {
1936+ obj = (lastInstance = obj)[key];
1937+ }
1938+ }
1939+ if (!bindFnToScope && isFunction(obj)) {
1940+ return bind(lastInstance, obj);
1941+ }
1942+ return obj;
1943+}
1944+
1945+/**
1946+ * Return the DOM siblings between the first and last node in the given array.
1947+ * @param {Array} array like object
1948+ * @returns {Array} the inputted object or a jqLite collection containing the nodes
1949+ */
1950+function getBlockNodes(nodes) {
1951+ // TODO(perf): update `nodes` instead of creating a new object?
1952+ var node = nodes[0];
1953+ var endNode = nodes[nodes.length - 1];
1954+ var blockNodes;
1955+
1956+ for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
1957+ if (blockNodes || nodes[i] !== node) {
1958+ if (!blockNodes) {
1959+ blockNodes = jqLite(slice.call(nodes, 0, i));
1960+ }
1961+ blockNodes.push(node);
1962+ }
1963+ }
1964+
1965+ return blockNodes || nodes;
1966+}
1967+
1968+
1969+/**
1970+ * Creates a new object without a prototype. This object is useful for lookup without having to
1971+ * guard against prototypically inherited properties via hasOwnProperty.
1972+ *
1973+ * Related micro-benchmarks:
1974+ * - http://jsperf.com/object-create2
1975+ * - http://jsperf.com/proto-map-lookup/2
1976+ * - http://jsperf.com/for-in-vs-object-keys2
1977+ *
1978+ * @returns {Object}
1979+ */
1980+function createMap() {
1981+ return Object.create(null);
1982+}
1983+
1984+var NODE_TYPE_ELEMENT = 1;
1985+var NODE_TYPE_ATTRIBUTE = 2;
1986+var NODE_TYPE_TEXT = 3;
1987+var NODE_TYPE_COMMENT = 8;
1988+var NODE_TYPE_DOCUMENT = 9;
1989+var NODE_TYPE_DOCUMENT_FRAGMENT = 11;
1990+
1991+/**
1992+ * @ngdoc type
1993+ * @name angular.Module
1994+ * @module ng
1995+ * @description
1996+ *
1997+ * Interface for configuring angular {@link angular.module modules}.
1998+ */
1999+
2000+function setupModuleLoader(window) {
2001+
2002+ var $injectorMinErr = minErr('$injector');
2003+ var ngMinErr = minErr('ng');
2004+
2005+ function ensure(obj, name, factory) {
2006+ return obj[name] || (obj[name] = factory());
2007+ }
2008+
2009+ var angular = ensure(window, 'angular', Object);
2010+
2011+ // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
2012+ angular.$$minErr = angular.$$minErr || minErr;
2013+
2014+ return ensure(angular, 'module', function() {
2015+ /** @type {Object.<string, angular.Module>} */
2016+ var modules = {};
2017+
2018+ /**
2019+ * @ngdoc function
2020+ * @name angular.module
2021+ * @module ng
2022+ * @description
2023+ *
2024+ * The `angular.module` is a global place for creating, registering and retrieving Angular
2025+ * modules.
2026+ * All modules (angular core or 3rd party) that should be available to an application must be
2027+ * registered using this mechanism.
2028+ *
2029+ * Passing one argument retrieves an existing {@link angular.Module},
2030+ * whereas passing more than one argument creates a new {@link angular.Module}
2031+ *
2032+ *
2033+ * # Module
2034+ *
2035+ * A module is a collection of services, directives, controllers, filters, and configuration information.
2036+ * `angular.module` is used to configure the {@link auto.$injector $injector}.
2037+ *
2038+ * ```js
2039+ * // Create a new module
2040+ * var myModule = angular.module('myModule', []);
2041+ *
2042+ * // register a new service
2043+ * myModule.value('appName', 'MyCoolApp');
2044+ *
2045+ * // configure existing services inside initialization blocks.
2046+ * myModule.config(['$locationProvider', function($locationProvider) {
2047+ * // Configure existing providers
2048+ * $locationProvider.hashPrefix('!');
2049+ * }]);
2050+ * ```
2051+ *
2052+ * Then you can create an injector and load your modules like this:
2053+ *
2054+ * ```js
2055+ * var injector = angular.injector(['ng', 'myModule'])
2056+ * ```
2057+ *
2058+ * However it's more likely that you'll just use
2059+ * {@link ng.directive:ngApp ngApp} or
2060+ * {@link angular.bootstrap} to simplify this process for you.
2061+ *
2062+ * @param {!string} name The name of the module to create or retrieve.
2063+ * @param {!Array.<string>=} requires If specified then new module is being created. If
2064+ * unspecified then the module is being retrieved for further configuration.
2065+ * @param {Function=} configFn Optional configuration function for the module. Same as
2066+ * {@link angular.Module#config Module#config()}.
2067+ * @returns {angular.Module} new module with the {@link angular.Module} api.
2068+ */
2069+ return function module(name, requires, configFn) {
2070+ var assertNotHasOwnProperty = function(name, context) {
2071+ if (name === 'hasOwnProperty') {
2072+ throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
2073+ }
2074+ };
2075+
2076+ assertNotHasOwnProperty(name, 'module');
2077+ if (requires && modules.hasOwnProperty(name)) {
2078+ modules[name] = null;
2079+ }
2080+ return ensure(modules, name, function() {
2081+ if (!requires) {
2082+ throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
2083+ "the module name or forgot to load it. If registering a module ensure that you " +
2084+ "specify the dependencies as the second argument.", name);
2085+ }
2086+
2087+ /** @type {!Array.<Array.<*>>} */
2088+ var invokeQueue = [];
2089+
2090+ /** @type {!Array.<Function>} */
2091+ var configBlocks = [];
2092+
2093+ /** @type {!Array.<Function>} */
2094+ var runBlocks = [];
2095+
2096+ var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
2097+
2098+ /** @type {angular.Module} */
2099+ var moduleInstance = {
2100+ // Private state
2101+ _invokeQueue: invokeQueue,
2102+ _configBlocks: configBlocks,
2103+ _runBlocks: runBlocks,
2104+
2105+ /**
2106+ * @ngdoc property
2107+ * @name angular.Module#requires
2108+ * @module ng
2109+ *
2110+ * @description
2111+ * Holds the list of modules which the injector will load before the current module is
2112+ * loaded.
2113+ */
2114+ requires: requires,
2115+
2116+ /**
2117+ * @ngdoc property
2118+ * @name angular.Module#name
2119+ * @module ng
2120+ *
2121+ * @description
2122+ * Name of the module.
2123+ */
2124+ name: name,
2125+
2126+
2127+ /**
2128+ * @ngdoc method
2129+ * @name angular.Module#provider
2130+ * @module ng
2131+ * @param {string} name service name
2132+ * @param {Function} providerType Construction function for creating new instance of the
2133+ * service.
2134+ * @description
2135+ * See {@link auto.$provide#provider $provide.provider()}.
2136+ */
2137+ provider: invokeLaterAndSetModuleName('$provide', 'provider'),
2138+
2139+ /**
2140+ * @ngdoc method
2141+ * @name angular.Module#factory
2142+ * @module ng
2143+ * @param {string} name service name
2144+ * @param {Function} providerFunction Function for creating new instance of the service.
2145+ * @description
2146+ * See {@link auto.$provide#factory $provide.factory()}.
2147+ */
2148+ factory: invokeLaterAndSetModuleName('$provide', 'factory'),
2149+
2150+ /**
2151+ * @ngdoc method
2152+ * @name angular.Module#service
2153+ * @module ng
2154+ * @param {string} name service name
2155+ * @param {Function} constructor A constructor function that will be instantiated.
2156+ * @description
2157+ * See {@link auto.$provide#service $provide.service()}.
2158+ */
2159+ service: invokeLaterAndSetModuleName('$provide', 'service'),
2160+
2161+ /**
2162+ * @ngdoc method
2163+ * @name angular.Module#value
2164+ * @module ng
2165+ * @param {string} name service name
2166+ * @param {*} object Service instance object.
2167+ * @description
2168+ * See {@link auto.$provide#value $provide.value()}.
2169+ */
2170+ value: invokeLater('$provide', 'value'),
2171+
2172+ /**
2173+ * @ngdoc method
2174+ * @name angular.Module#constant
2175+ * @module ng
2176+ * @param {string} name constant name
2177+ * @param {*} object Constant value.
2178+ * @description
2179+ * Because the constants are fixed, they get applied before other provide methods.
2180+ * See {@link auto.$provide#constant $provide.constant()}.
2181+ */
2182+ constant: invokeLater('$provide', 'constant', 'unshift'),
2183+
2184+ /**
2185+ * @ngdoc method
2186+ * @name angular.Module#decorator
2187+ * @module ng
2188+ * @param {string} name The name of the service to decorate.
2189+ * @param {Function} decorFn This function will be invoked when the service needs to be
2190+ * instantiated and should return the decorated service instance.
2191+ * @description
2192+ * See {@link auto.$provide#decorator $provide.decorator()}.
2193+ */
2194+ decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
2195+
2196+ /**
2197+ * @ngdoc method
2198+ * @name angular.Module#animation
2199+ * @module ng
2200+ * @param {string} name animation name
2201+ * @param {Function} animationFactory Factory function for creating new instance of an
2202+ * animation.
2203+ * @description
2204+ *
2205+ * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
2206+ *
2207+ *
2208+ * Defines an animation hook that can be later used with
2209+ * {@link $animate $animate} service and directives that use this service.
2210+ *
2211+ * ```js
2212+ * module.animation('.animation-name', function($inject1, $inject2) {
2213+ * return {
2214+ * eventName : function(element, done) {
2215+ * //code to run the animation
2216+ * //once complete, then run done()
2217+ * return function cancellationFunction(element) {
2218+ * //code to cancel the animation
2219+ * }
2220+ * }
2221+ * }
2222+ * })
2223+ * ```
2224+ *
2225+ * See {@link ng.$animateProvider#register $animateProvider.register()} and
2226+ * {@link ngAnimate ngAnimate module} for more information.
2227+ */
2228+ animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
2229+
2230+ /**
2231+ * @ngdoc method
2232+ * @name angular.Module#filter
2233+ * @module ng
2234+ * @param {string} name Filter name - this must be a valid angular expression identifier
2235+ * @param {Function} filterFactory Factory function for creating new instance of filter.
2236+ * @description
2237+ * See {@link ng.$filterProvider#register $filterProvider.register()}.
2238+ *
2239+ * <div class="alert alert-warning">
2240+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
2241+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
2242+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
2243+ * (`myapp_subsection_filterx`).
2244+ * </div>
2245+ */
2246+ filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
2247+
2248+ /**
2249+ * @ngdoc method
2250+ * @name angular.Module#controller
2251+ * @module ng
2252+ * @param {string|Object} name Controller name, or an object map of controllers where the
2253+ * keys are the names and the values are the constructors.
2254+ * @param {Function} constructor Controller constructor function.
2255+ * @description
2256+ * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
2257+ */
2258+ controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
2259+
2260+ /**
2261+ * @ngdoc method
2262+ * @name angular.Module#directive
2263+ * @module ng
2264+ * @param {string|Object} name Directive name, or an object map of directives where the
2265+ * keys are the names and the values are the factories.
2266+ * @param {Function} directiveFactory Factory function for creating new instance of
2267+ * directives.
2268+ * @description
2269+ * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
2270+ */
2271+ directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
2272+
2273+ /**
2274+ * @ngdoc method
2275+ * @name angular.Module#component
2276+ * @module ng
2277+ * @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp)
2278+ * @param {Object} options Component definition object (a simplified
2279+ * {@link ng.$compile#directive-definition-object directive definition object})
2280+ *
2281+ * @description
2282+ * See {@link ng.$compileProvider#component $compileProvider.component()}.
2283+ */
2284+ component: invokeLaterAndSetModuleName('$compileProvider', 'component'),
2285+
2286+ /**
2287+ * @ngdoc method
2288+ * @name angular.Module#config
2289+ * @module ng
2290+ * @param {Function} configFn Execute this function on module load. Useful for service
2291+ * configuration.
2292+ * @description
2293+ * Use this method to register work which needs to be performed on module loading.
2294+ * For more about how to configure services, see
2295+ * {@link providers#provider-recipe Provider Recipe}.
2296+ */
2297+ config: config,
2298+
2299+ /**
2300+ * @ngdoc method
2301+ * @name angular.Module#run
2302+ * @module ng
2303+ * @param {Function} initializationFn Execute this function after injector creation.
2304+ * Useful for application initialization.
2305+ * @description
2306+ * Use this method to register work which should be performed when the injector is done
2307+ * loading all modules.
2308+ */
2309+ run: function(block) {
2310+ runBlocks.push(block);
2311+ return this;
2312+ }
2313+ };
2314+
2315+ if (configFn) {
2316+ config(configFn);
2317+ }
2318+
2319+ return moduleInstance;
2320+
2321+ /**
2322+ * @param {string} provider
2323+ * @param {string} method
2324+ * @param {String=} insertMethod
2325+ * @returns {angular.Module}
2326+ */
2327+ function invokeLater(provider, method, insertMethod, queue) {
2328+ if (!queue) queue = invokeQueue;
2329+ return function() {
2330+ queue[insertMethod || 'push']([provider, method, arguments]);
2331+ return moduleInstance;
2332+ };
2333+ }
2334+
2335+ /**
2336+ * @param {string} provider
2337+ * @param {string} method
2338+ * @returns {angular.Module}
2339+ */
2340+ function invokeLaterAndSetModuleName(provider, method) {
2341+ return function(recipeName, factoryFunction) {
2342+ if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
2343+ invokeQueue.push([provider, method, arguments]);
2344+ return moduleInstance;
2345+ };
2346+ }
2347+ });
2348+ };
2349+ });
2350+
2351+}
2352+
2353+/* global shallowCopy: true */
2354+
2355+/**
2356+ * Creates a shallow copy of an object, an array or a primitive.
2357+ *
2358+ * Assumes that there are no proto properties for objects.
2359+ */
2360+function shallowCopy(src, dst) {
2361+ if (isArray(src)) {
2362+ dst = dst || [];
2363+
2364+ for (var i = 0, ii = src.length; i < ii; i++) {
2365+ dst[i] = src[i];
2366+ }
2367+ } else if (isObject(src)) {
2368+ dst = dst || {};
2369+
2370+ for (var key in src) {
2371+ if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
2372+ dst[key] = src[key];
2373+ }
2374+ }
2375+ }
2376+
2377+ return dst || src;
2378+}
2379+
2380+/* global toDebugString: true */
2381+
2382+function serializeObject(obj) {
2383+ var seen = [];
2384+
2385+ return JSON.stringify(obj, function(key, val) {
2386+ val = toJsonReplacer(key, val);
2387+ if (isObject(val)) {
2388+
2389+ if (seen.indexOf(val) >= 0) return '...';
2390+
2391+ seen.push(val);
2392+ }
2393+ return val;
2394+ });
2395+}
2396+
2397+function toDebugString(obj) {
2398+ if (typeof obj === 'function') {
2399+ return obj.toString().replace(/ \{[\s\S]*$/, '');
2400+ } else if (isUndefined(obj)) {
2401+ return 'undefined';
2402+ } else if (typeof obj !== 'string') {
2403+ return serializeObject(obj);
2404+ }
2405+ return obj;
2406+}
2407+
2408+/* global angularModule: true,
2409+ version: true,
2410+
2411+ $CompileProvider,
2412+
2413+ htmlAnchorDirective,
2414+ inputDirective,
2415+ inputDirective,
2416+ formDirective,
2417+ scriptDirective,
2418+ selectDirective,
2419+ styleDirective,
2420+ optionDirective,
2421+ ngBindDirective,
2422+ ngBindHtmlDirective,
2423+ ngBindTemplateDirective,
2424+ ngClassDirective,
2425+ ngClassEvenDirective,
2426+ ngClassOddDirective,
2427+ ngCloakDirective,
2428+ ngControllerDirective,
2429+ ngFormDirective,
2430+ ngHideDirective,
2431+ ngIfDirective,
2432+ ngIncludeDirective,
2433+ ngIncludeFillContentDirective,
2434+ ngInitDirective,
2435+ ngNonBindableDirective,
2436+ ngPluralizeDirective,
2437+ ngRepeatDirective,
2438+ ngShowDirective,
2439+ ngStyleDirective,
2440+ ngSwitchDirective,
2441+ ngSwitchWhenDirective,
2442+ ngSwitchDefaultDirective,
2443+ ngOptionsDirective,
2444+ ngTranscludeDirective,
2445+ ngModelDirective,
2446+ ngListDirective,
2447+ ngChangeDirective,
2448+ patternDirective,
2449+ patternDirective,
2450+ requiredDirective,
2451+ requiredDirective,
2452+ minlengthDirective,
2453+ minlengthDirective,
2454+ maxlengthDirective,
2455+ maxlengthDirective,
2456+ ngValueDirective,
2457+ ngModelOptionsDirective,
2458+ ngAttributeAliasDirectives,
2459+ ngEventDirectives,
2460+
2461+ $AnchorScrollProvider,
2462+ $AnimateProvider,
2463+ $CoreAnimateCssProvider,
2464+ $$CoreAnimateJsProvider,
2465+ $$CoreAnimateQueueProvider,
2466+ $$AnimateRunnerFactoryProvider,
2467+ $$AnimateAsyncRunFactoryProvider,
2468+ $BrowserProvider,
2469+ $CacheFactoryProvider,
2470+ $ControllerProvider,
2471+ $DateProvider,
2472+ $DocumentProvider,
2473+ $ExceptionHandlerProvider,
2474+ $FilterProvider,
2475+ $$ForceReflowProvider,
2476+ $InterpolateProvider,
2477+ $IntervalProvider,
2478+ $$HashMapProvider,
2479+ $HttpProvider,
2480+ $HttpParamSerializerProvider,
2481+ $HttpParamSerializerJQLikeProvider,
2482+ $HttpBackendProvider,
2483+ $xhrFactoryProvider,
2484+ $jsonpCallbacksProvider,
2485+ $LocationProvider,
2486+ $LogProvider,
2487+ $ParseProvider,
2488+ $RootScopeProvider,
2489+ $QProvider,
2490+ $$QProvider,
2491+ $$SanitizeUriProvider,
2492+ $SceProvider,
2493+ $SceDelegateProvider,
2494+ $SnifferProvider,
2495+ $TemplateCacheProvider,
2496+ $TemplateRequestProvider,
2497+ $$TestabilityProvider,
2498+ $TimeoutProvider,
2499+ $$RAFProvider,
2500+ $WindowProvider,
2501+ $$jqLiteProvider,
2502+ $$CookieReaderProvider
2503+*/
2504+
2505+
2506+/**
2507+ * @ngdoc object
2508+ * @name angular.version
2509+ * @module ng
2510+ * @description
2511+ * An object that contains information about the current AngularJS version.
2512+ *
2513+ * This object has the following properties:
2514+ *
2515+ * - `full` – `{string}` – Full version string, such as "0.9.18".
2516+ * - `major` – `{number}` – Major version number, such as "0".
2517+ * - `minor` – `{number}` – Minor version number, such as "9".
2518+ * - `dot` – `{number}` – Dot version number, such as "18".
2519+ * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2520+ */
2521+var version = {
2522+ full: '1.5.8', // all of these placeholder strings will be replaced by grunt's
2523+ major: 1, // package task
2524+ minor: 5,
2525+ dot: 8,
2526+ codeName: 'arbitrary-fallbacks'
2527+};
2528+
2529+
2530+function publishExternalAPI(angular) {
2531+ extend(angular, {
2532+ 'bootstrap': bootstrap,
2533+ 'copy': copy,
2534+ 'extend': extend,
2535+ 'merge': merge,
2536+ 'equals': equals,
2537+ 'element': jqLite,
2538+ 'forEach': forEach,
2539+ 'injector': createInjector,
2540+ 'noop': noop,
2541+ 'bind': bind,
2542+ 'toJson': toJson,
2543+ 'fromJson': fromJson,
2544+ 'identity': identity,
2545+ 'isUndefined': isUndefined,
2546+ 'isDefined': isDefined,
2547+ 'isString': isString,
2548+ 'isFunction': isFunction,
2549+ 'isObject': isObject,
2550+ 'isNumber': isNumber,
2551+ 'isElement': isElement,
2552+ 'isArray': isArray,
2553+ 'version': version,
2554+ 'isDate': isDate,
2555+ 'lowercase': lowercase,
2556+ 'uppercase': uppercase,
2557+ 'callbacks': {$$counter: 0},
2558+ 'getTestability': getTestability,
2559+ '$$minErr': minErr,
2560+ '$$csp': csp,
2561+ 'reloadWithDebugInfo': reloadWithDebugInfo
2562+ });
2563+
2564+ angularModule = setupModuleLoader(window);
2565+
2566+ angularModule('ng', ['ngLocale'], ['$provide',
2567+ function ngModule($provide) {
2568+ // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
2569+ $provide.provider({
2570+ $$sanitizeUri: $$SanitizeUriProvider
2571+ });
2572+ $provide.provider('$compile', $CompileProvider).
2573+ directive({
2574+ a: htmlAnchorDirective,
2575+ input: inputDirective,
2576+ textarea: inputDirective,
2577+ form: formDirective,
2578+ script: scriptDirective,
2579+ select: selectDirective,
2580+ style: styleDirective,
2581+ option: optionDirective,
2582+ ngBind: ngBindDirective,
2583+ ngBindHtml: ngBindHtmlDirective,
2584+ ngBindTemplate: ngBindTemplateDirective,
2585+ ngClass: ngClassDirective,
2586+ ngClassEven: ngClassEvenDirective,
2587+ ngClassOdd: ngClassOddDirective,
2588+ ngCloak: ngCloakDirective,
2589+ ngController: ngControllerDirective,
2590+ ngForm: ngFormDirective,
2591+ ngHide: ngHideDirective,
2592+ ngIf: ngIfDirective,
2593+ ngInclude: ngIncludeDirective,
2594+ ngInit: ngInitDirective,
2595+ ngNonBindable: ngNonBindableDirective,
2596+ ngPluralize: ngPluralizeDirective,
2597+ ngRepeat: ngRepeatDirective,
2598+ ngShow: ngShowDirective,
2599+ ngStyle: ngStyleDirective,
2600+ ngSwitch: ngSwitchDirective,
2601+ ngSwitchWhen: ngSwitchWhenDirective,
2602+ ngSwitchDefault: ngSwitchDefaultDirective,
2603+ ngOptions: ngOptionsDirective,
2604+ ngTransclude: ngTranscludeDirective,
2605+ ngModel: ngModelDirective,
2606+ ngList: ngListDirective,
2607+ ngChange: ngChangeDirective,
2608+ pattern: patternDirective,
2609+ ngPattern: patternDirective,
2610+ required: requiredDirective,
2611+ ngRequired: requiredDirective,
2612+ minlength: minlengthDirective,
2613+ ngMinlength: minlengthDirective,
2614+ maxlength: maxlengthDirective,
2615+ ngMaxlength: maxlengthDirective,
2616+ ngValue: ngValueDirective,
2617+ ngModelOptions: ngModelOptionsDirective
2618+ }).
2619+ directive({
2620+ ngInclude: ngIncludeFillContentDirective
2621+ }).
2622+ directive(ngAttributeAliasDirectives).
2623+ directive(ngEventDirectives);
2624+ $provide.provider({
2625+ $anchorScroll: $AnchorScrollProvider,
2626+ $animate: $AnimateProvider,
2627+ $animateCss: $CoreAnimateCssProvider,
2628+ $$animateJs: $$CoreAnimateJsProvider,
2629+ $$animateQueue: $$CoreAnimateQueueProvider,
2630+ $$AnimateRunner: $$AnimateRunnerFactoryProvider,
2631+ $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,
2632+ $browser: $BrowserProvider,
2633+ $cacheFactory: $CacheFactoryProvider,
2634+ $controller: $ControllerProvider,
2635+ $document: $DocumentProvider,
2636+ $exceptionHandler: $ExceptionHandlerProvider,
2637+ $filter: $FilterProvider,
2638+ $$forceReflow: $$ForceReflowProvider,
2639+ $interpolate: $InterpolateProvider,
2640+ $interval: $IntervalProvider,
2641+ $http: $HttpProvider,
2642+ $httpParamSerializer: $HttpParamSerializerProvider,
2643+ $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
2644+ $httpBackend: $HttpBackendProvider,
2645+ $xhrFactory: $xhrFactoryProvider,
2646+ $jsonpCallbacks: $jsonpCallbacksProvider,
2647+ $location: $LocationProvider,
2648+ $log: $LogProvider,
2649+ $parse: $ParseProvider,
2650+ $rootScope: $RootScopeProvider,
2651+ $q: $QProvider,
2652+ $$q: $$QProvider,
2653+ $sce: $SceProvider,
2654+ $sceDelegate: $SceDelegateProvider,
2655+ $sniffer: $SnifferProvider,
2656+ $templateCache: $TemplateCacheProvider,
2657+ $templateRequest: $TemplateRequestProvider,
2658+ $$testability: $$TestabilityProvider,
2659+ $timeout: $TimeoutProvider,
2660+ $window: $WindowProvider,
2661+ $$rAF: $$RAFProvider,
2662+ $$jqLite: $$jqLiteProvider,
2663+ $$HashMap: $$HashMapProvider,
2664+ $$cookieReader: $$CookieReaderProvider
2665+ });
2666+ }
2667+ ]);
2668+}
2669+
2670+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2671+ * Any commits to this file should be reviewed with security in mind. *
2672+ * Changes to this file can potentially create security vulnerabilities. *
2673+ * An approval from 2 Core members with history of modifying *
2674+ * this file is required. *
2675+ * *
2676+ * Does the change somehow allow for arbitrary javascript to be executed? *
2677+ * Or allows for someone to change the prototype of built-in objects? *
2678+ * Or gives undesired access to variables likes document or window? *
2679+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2680+
2681+/* global JQLitePrototype: true,
2682+ addEventListenerFn: true,
2683+ removeEventListenerFn: true,
2684+ BOOLEAN_ATTR: true,
2685+ ALIASED_ATTR: true,
2686+*/
2687+
2688+//////////////////////////////////
2689+//JQLite
2690+//////////////////////////////////
2691+
2692+/**
2693+ * @ngdoc function
2694+ * @name angular.element
2695+ * @module ng
2696+ * @kind function
2697+ *
2698+ * @description
2699+ * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
2700+ *
2701+ * If jQuery is available, `angular.element` is an alias for the
2702+ * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
2703+ * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**.
2704+ *
2705+ * jqLite is a tiny, API-compatible subset of jQuery that allows
2706+ * Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most
2707+ * commonly needed functionality with the goal of having a very small footprint.
2708+ *
2709+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the
2710+ * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a
2711+ * specific version of jQuery if multiple versions exist on the page.
2712+ *
2713+ * <div class="alert alert-info">**Note:** All element references in Angular are always wrapped with jQuery or
2714+ * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div>
2715+ *
2716+ * <div class="alert alert-warning">**Note:** Keep in mind that this function will not find elements
2717+ * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)`
2718+ * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div>
2719+ *
2720+ * ## Angular's jqLite
2721+ * jqLite provides only the following jQuery methods:
2722+ *
2723+ * - [`addClass()`](http://api.jquery.com/addClass/) - Does not support a function as first argument
2724+ * - [`after()`](http://api.jquery.com/after/)
2725+ * - [`append()`](http://api.jquery.com/append/)
2726+ * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
2727+ * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
2728+ * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
2729+ * - [`clone()`](http://api.jquery.com/clone/)
2730+ * - [`contents()`](http://api.jquery.com/contents/)
2731+ * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`.
2732+ * As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing.
2733+ * - [`data()`](http://api.jquery.com/data/)
2734+ * - [`detach()`](http://api.jquery.com/detach/)
2735+ * - [`empty()`](http://api.jquery.com/empty/)
2736+ * - [`eq()`](http://api.jquery.com/eq/)
2737+ * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
2738+ * - [`hasClass()`](http://api.jquery.com/hasClass/)
2739+ * - [`html()`](http://api.jquery.com/html/)
2740+ * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
2741+ * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
2742+ * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
2743+ * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
2744+ * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
2745+ * - [`prepend()`](http://api.jquery.com/prepend/)
2746+ * - [`prop()`](http://api.jquery.com/prop/)
2747+ * - [`ready()`](http://api.jquery.com/ready/)
2748+ * - [`remove()`](http://api.jquery.com/remove/)
2749+ * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
2750+ * - [`removeClass()`](http://api.jquery.com/removeClass/) - Does not support a function as first argument
2751+ * - [`removeData()`](http://api.jquery.com/removeData/)
2752+ * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
2753+ * - [`text()`](http://api.jquery.com/text/)
2754+ * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - Does not support a function as first argument
2755+ * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers
2756+ * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
2757+ * - [`val()`](http://api.jquery.com/val/)
2758+ * - [`wrap()`](http://api.jquery.com/wrap/)
2759+ *
2760+ * ## jQuery/jqLite Extras
2761+ * Angular also provides the following additional methods and events to both jQuery and jqLite:
2762+ *
2763+ * ### Events
2764+ * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
2765+ * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
2766+ * element before it is removed.
2767+ *
2768+ * ### Methods
2769+ * - `controller(name)` - retrieves the controller of the current element or its parent. By default
2770+ * retrieves controller associated with the `ngController` directive. If `name` is provided as
2771+ * camelCase directive name, then the controller for this directive will be retrieved (e.g.
2772+ * `'ngModel'`).
2773+ * - `injector()` - retrieves the injector of the current element or its parent.
2774+ * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
2775+ * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
2776+ * be enabled.
2777+ * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
2778+ * current element. This getter should be used only on elements that contain a directive which starts a new isolate
2779+ * scope. Calling `scope()` on this element always returns the original non-isolate scope.
2780+ * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
2781+ * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
2782+ * parent element is reached.
2783+ *
2784+ * @knownIssue You cannot spy on `angular.element` if you are using Jasmine version 1.x. See
2785+ * https://github.com/angular/angular.js/issues/14251 for more information.
2786+ *
2787+ * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
2788+ * @returns {Object} jQuery object.
2789+ */
2790+
2791+JQLite.expando = 'ng339';
2792+
2793+var jqCache = JQLite.cache = {},
2794+ jqId = 1,
2795+ addEventListenerFn = function(element, type, fn) {
2796+ element.addEventListener(type, fn, false);
2797+ },
2798+ removeEventListenerFn = function(element, type, fn) {
2799+ element.removeEventListener(type, fn, false);
2800+ };
2801+
2802+/*
2803+ * !!! This is an undocumented "private" function !!!
2804+ */
2805+JQLite._data = function(node) {
2806+ //jQuery always returns an object on cache miss
2807+ return this.cache[node[this.expando]] || {};
2808+};
2809+
2810+function jqNextId() { return ++jqId; }
2811+
2812+
2813+var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
2814+var MOZ_HACK_REGEXP = /^moz([A-Z])/;
2815+var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
2816+var jqLiteMinErr = minErr('jqLite');
2817+
2818+/**
2819+ * Converts snake_case to camelCase.
2820+ * Also there is special case for Moz prefix starting with upper case letter.
2821+ * @param name Name to normalize
2822+ */
2823+function camelCase(name) {
2824+ return name.
2825+ replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
2826+ return offset ? letter.toUpperCase() : letter;
2827+ }).
2828+ replace(MOZ_HACK_REGEXP, 'Moz$1');
2829+}
2830+
2831+var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
2832+var HTML_REGEXP = /<|&#?\w+;/;
2833+var TAG_NAME_REGEXP = /<([\w:-]+)/;
2834+var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi;
2835+
2836+var wrapMap = {
2837+ 'option': [1, '<select multiple="multiple">', '</select>'],
2838+
2839+ 'thead': [1, '<table>', '</table>'],
2840+ 'col': [2, '<table><colgroup>', '</colgroup></table>'],
2841+ 'tr': [2, '<table><tbody>', '</tbody></table>'],
2842+ 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
2843+ '_default': [0, "", ""]
2844+};
2845+
2846+wrapMap.optgroup = wrapMap.option;
2847+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
2848+wrapMap.th = wrapMap.td;
2849+
2850+
2851+function jqLiteIsTextNode(html) {
2852+ return !HTML_REGEXP.test(html);
2853+}
2854+
2855+function jqLiteAcceptsData(node) {
2856+ // The window object can accept data but has no nodeType
2857+ // Otherwise we are only interested in elements (1) and documents (9)
2858+ var nodeType = node.nodeType;
2859+ return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
2860+}
2861+
2862+function jqLiteHasData(node) {
2863+ for (var key in jqCache[node.ng339]) {
2864+ return true;
2865+ }
2866+ return false;
2867+}
2868+
2869+function jqLiteCleanData(nodes) {
2870+ for (var i = 0, ii = nodes.length; i < ii; i++) {
2871+ jqLiteRemoveData(nodes[i]);
2872+ }
2873+}
2874+
2875+function jqLiteBuildFragment(html, context) {
2876+ var tmp, tag, wrap,
2877+ fragment = context.createDocumentFragment(),
2878+ nodes = [], i;
2879+
2880+ if (jqLiteIsTextNode(html)) {
2881+ // Convert non-html into a text node
2882+ nodes.push(context.createTextNode(html));
2883+ } else {
2884+ // Convert html into DOM nodes
2885+ tmp = fragment.appendChild(context.createElement("div"));
2886+ tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
2887+ wrap = wrapMap[tag] || wrapMap._default;
2888+ tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
2889+
2890+ // Descend through wrappers to the right content
2891+ i = wrap[0];
2892+ while (i--) {
2893+ tmp = tmp.lastChild;
2894+ }
2895+
2896+ nodes = concat(nodes, tmp.childNodes);
2897+
2898+ tmp = fragment.firstChild;
2899+ tmp.textContent = "";
2900+ }
2901+
2902+ // Remove wrapper from fragment
2903+ fragment.textContent = "";
2904+ fragment.innerHTML = ""; // Clear inner HTML
2905+ forEach(nodes, function(node) {
2906+ fragment.appendChild(node);
2907+ });
2908+
2909+ return fragment;
2910+}
2911+
2912+function jqLiteParseHTML(html, context) {
2913+ context = context || window.document;
2914+ var parsed;
2915+
2916+ if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
2917+ return [context.createElement(parsed[1])];
2918+ }
2919+
2920+ if ((parsed = jqLiteBuildFragment(html, context))) {
2921+ return parsed.childNodes;
2922+ }
2923+
2924+ return [];
2925+}
2926+
2927+function jqLiteWrapNode(node, wrapper) {
2928+ var parent = node.parentNode;
2929+
2930+ if (parent) {
2931+ parent.replaceChild(wrapper, node);
2932+ }
2933+
2934+ wrapper.appendChild(node);
2935+}
2936+
2937+
2938+// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
2939+var jqLiteContains = window.Node.prototype.contains || function(arg) {
2940+ // jshint bitwise: false
2941+ return !!(this.compareDocumentPosition(arg) & 16);
2942+ // jshint bitwise: true
2943+};
2944+
2945+/////////////////////////////////////////////
2946+function JQLite(element) {
2947+ if (element instanceof JQLite) {
2948+ return element;
2949+ }
2950+
2951+ var argIsString;
2952+
2953+ if (isString(element)) {
2954+ element = trim(element);
2955+ argIsString = true;
2956+ }
2957+ if (!(this instanceof JQLite)) {
2958+ if (argIsString && element.charAt(0) != '<') {
2959+ throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
2960+ }
2961+ return new JQLite(element);
2962+ }
2963+
2964+ if (argIsString) {
2965+ jqLiteAddNodes(this, jqLiteParseHTML(element));
2966+ } else {
2967+ jqLiteAddNodes(this, element);
2968+ }
2969+}
2970+
2971+function jqLiteClone(element) {
2972+ return element.cloneNode(true);
2973+}
2974+
2975+function jqLiteDealoc(element, onlyDescendants) {
2976+ if (!onlyDescendants) jqLiteRemoveData(element);
2977+
2978+ if (element.querySelectorAll) {
2979+ var descendants = element.querySelectorAll('*');
2980+ for (var i = 0, l = descendants.length; i < l; i++) {
2981+ jqLiteRemoveData(descendants[i]);
2982+ }
2983+ }
2984+}
2985+
2986+function jqLiteOff(element, type, fn, unsupported) {
2987+ if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
2988+
2989+ var expandoStore = jqLiteExpandoStore(element);
2990+ var events = expandoStore && expandoStore.events;
2991+ var handle = expandoStore && expandoStore.handle;
2992+
2993+ if (!handle) return; //no listeners registered
2994+
2995+ if (!type) {
2996+ for (type in events) {
2997+ if (type !== '$destroy') {
2998+ removeEventListenerFn(element, type, handle);
2999+ }
3000+ delete events[type];
3001+ }
3002+ } else {
3003+
3004+ var removeHandler = function(type) {
3005+ var listenerFns = events[type];
3006+ if (isDefined(fn)) {
3007+ arrayRemove(listenerFns || [], fn);
3008+ }
3009+ if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
3010+ removeEventListenerFn(element, type, handle);
3011+ delete events[type];
3012+ }
3013+ };
3014+
3015+ forEach(type.split(' '), function(type) {
3016+ removeHandler(type);
3017+ if (MOUSE_EVENT_MAP[type]) {
3018+ removeHandler(MOUSE_EVENT_MAP[type]);
3019+ }
3020+ });
3021+ }
3022+}
3023+
3024+function jqLiteRemoveData(element, name) {
3025+ var expandoId = element.ng339;
3026+ var expandoStore = expandoId && jqCache[expandoId];
3027+
3028+ if (expandoStore) {
3029+ if (name) {
3030+ delete expandoStore.data[name];
3031+ return;
3032+ }
3033+
3034+ if (expandoStore.handle) {
3035+ if (expandoStore.events.$destroy) {
3036+ expandoStore.handle({}, '$destroy');
3037+ }
3038+ jqLiteOff(element);
3039+ }
3040+ delete jqCache[expandoId];
3041+ element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
3042+ }
3043+}
3044+
3045+
3046+function jqLiteExpandoStore(element, createIfNecessary) {
3047+ var expandoId = element.ng339,
3048+ expandoStore = expandoId && jqCache[expandoId];
3049+
3050+ if (createIfNecessary && !expandoStore) {
3051+ element.ng339 = expandoId = jqNextId();
3052+ expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};
3053+ }
3054+
3055+ return expandoStore;
3056+}
3057+
3058+
3059+function jqLiteData(element, key, value) {
3060+ if (jqLiteAcceptsData(element)) {
3061+
3062+ var isSimpleSetter = isDefined(value);
3063+ var isSimpleGetter = !isSimpleSetter && key && !isObject(key);
3064+ var massGetter = !key;
3065+ var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);
3066+ var data = expandoStore && expandoStore.data;
3067+
3068+ if (isSimpleSetter) { // data('key', value)
3069+ data[key] = value;
3070+ } else {
3071+ if (massGetter) { // data()
3072+ return data;
3073+ } else {
3074+ if (isSimpleGetter) { // data('key')
3075+ // don't force creation of expandoStore if it doesn't exist yet
3076+ return data && data[key];
3077+ } else { // mass-setter: data({key1: val1, key2: val2})
3078+ extend(data, key);
3079+ }
3080+ }
3081+ }
3082+ }
3083+}
3084+
3085+function jqLiteHasClass(element, selector) {
3086+ if (!element.getAttribute) return false;
3087+ return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
3088+ indexOf(" " + selector + " ") > -1);
3089+}
3090+
3091+function jqLiteRemoveClass(element, cssClasses) {
3092+ if (cssClasses && element.setAttribute) {
3093+ forEach(cssClasses.split(' '), function(cssClass) {
3094+ element.setAttribute('class', trim(
3095+ (" " + (element.getAttribute('class') || '') + " ")
3096+ .replace(/[\n\t]/g, " ")
3097+ .replace(" " + trim(cssClass) + " ", " "))
3098+ );
3099+ });
3100+ }
3101+}
3102+
3103+function jqLiteAddClass(element, cssClasses) {
3104+ if (cssClasses && element.setAttribute) {
3105+ var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
3106+ .replace(/[\n\t]/g, " ");
3107+
3108+ forEach(cssClasses.split(' '), function(cssClass) {
3109+ cssClass = trim(cssClass);
3110+ if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
3111+ existingClasses += cssClass + ' ';
3112+ }
3113+ });
3114+
3115+ element.setAttribute('class', trim(existingClasses));
3116+ }
3117+}
3118+
3119+
3120+function jqLiteAddNodes(root, elements) {
3121+ // THIS CODE IS VERY HOT. Don't make changes without benchmarking.
3122+
3123+ if (elements) {
3124+
3125+ // if a Node (the most common case)
3126+ if (elements.nodeType) {
3127+ root[root.length++] = elements;
3128+ } else {
3129+ var length = elements.length;
3130+
3131+ // if an Array or NodeList and not a Window
3132+ if (typeof length === 'number' && elements.window !== elements) {
3133+ if (length) {
3134+ for (var i = 0; i < length; i++) {
3135+ root[root.length++] = elements[i];
3136+ }
3137+ }
3138+ } else {
3139+ root[root.length++] = elements;
3140+ }
3141+ }
3142+ }
3143+}
3144+
3145+
3146+function jqLiteController(element, name) {
3147+ return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
3148+}
3149+
3150+function jqLiteInheritedData(element, name, value) {
3151+ // if element is the document object work with the html element instead
3152+ // this makes $(document).scope() possible
3153+ if (element.nodeType == NODE_TYPE_DOCUMENT) {
3154+ element = element.documentElement;
3155+ }
3156+ var names = isArray(name) ? name : [name];
3157+
3158+ while (element) {
3159+ for (var i = 0, ii = names.length; i < ii; i++) {
3160+ if (isDefined(value = jqLite.data(element, names[i]))) return value;
3161+ }
3162+
3163+ // If dealing with a document fragment node with a host element, and no parent, use the host
3164+ // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
3165+ // to lookup parent controllers.
3166+ element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);
3167+ }
3168+}
3169+
3170+function jqLiteEmpty(element) {
3171+ jqLiteDealoc(element, true);
3172+ while (element.firstChild) {
3173+ element.removeChild(element.firstChild);
3174+ }
3175+}
3176+
3177+function jqLiteRemove(element, keepData) {
3178+ if (!keepData) jqLiteDealoc(element);
3179+ var parent = element.parentNode;
3180+ if (parent) parent.removeChild(element);
3181+}
3182+
3183+
3184+function jqLiteDocumentLoaded(action, win) {
3185+ win = win || window;
3186+ if (win.document.readyState === 'complete') {
3187+ // Force the action to be run async for consistent behavior
3188+ // from the action's point of view
3189+ // i.e. it will definitely not be in a $apply
3190+ win.setTimeout(action);
3191+ } else {
3192+ // No need to unbind this handler as load is only ever called once
3193+ jqLite(win).on('load', action);
3194+ }
3195+}
3196+
3197+//////////////////////////////////////////
3198+// Functions which are declared directly.
3199+//////////////////////////////////////////
3200+var JQLitePrototype = JQLite.prototype = {
3201+ ready: function(fn) {
3202+ var fired = false;
3203+
3204+ function trigger() {
3205+ if (fired) return;
3206+ fired = true;
3207+ fn();
3208+ }
3209+
3210+ // check if document is already loaded
3211+ if (window.document.readyState === 'complete') {
3212+ window.setTimeout(trigger);
3213+ } else {
3214+ this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
3215+ // we can not use jqLite since we are not done loading and jQuery could be loaded later.
3216+ // jshint -W064
3217+ JQLite(window).on('load', trigger); // fallback to window.onload for others
3218+ // jshint +W064
3219+ }
3220+ },
3221+ toString: function() {
3222+ var value = [];
3223+ forEach(this, function(e) { value.push('' + e);});
3224+ return '[' + value.join(', ') + ']';
3225+ },
3226+
3227+ eq: function(index) {
3228+ return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
3229+ },
3230+
3231+ length: 0,
3232+ push: push,
3233+ sort: [].sort,
3234+ splice: [].splice
3235+};
3236+
3237+//////////////////////////////////////////
3238+// Functions iterating getter/setters.
3239+// these functions return self on setter and
3240+// value on get.
3241+//////////////////////////////////////////
3242+var BOOLEAN_ATTR = {};
3243+forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
3244+ BOOLEAN_ATTR[lowercase(value)] = value;
3245+});
3246+var BOOLEAN_ELEMENTS = {};
3247+forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
3248+ BOOLEAN_ELEMENTS[value] = true;
3249+});
3250+var ALIASED_ATTR = {
3251+ 'ngMinlength': 'minlength',
3252+ 'ngMaxlength': 'maxlength',
3253+ 'ngMin': 'min',
3254+ 'ngMax': 'max',
3255+ 'ngPattern': 'pattern'
3256+};
3257+
3258+function getBooleanAttrName(element, name) {
3259+ // check dom last since we will most likely fail on name
3260+ var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
3261+
3262+ // booleanAttr is here twice to minimize DOM access
3263+ return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
3264+}
3265+
3266+function getAliasedAttrName(name) {
3267+ return ALIASED_ATTR[name];
3268+}
3269+
3270+forEach({
3271+ data: jqLiteData,
3272+ removeData: jqLiteRemoveData,
3273+ hasData: jqLiteHasData,
3274+ cleanData: jqLiteCleanData
3275+}, function(fn, name) {
3276+ JQLite[name] = fn;
3277+});
3278+
3279+forEach({
3280+ data: jqLiteData,
3281+ inheritedData: jqLiteInheritedData,
3282+
3283+ scope: function(element) {
3284+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
3285+ return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
3286+ },
3287+
3288+ isolateScope: function(element) {
3289+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
3290+ return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
3291+ },
3292+
3293+ controller: jqLiteController,
3294+
3295+ injector: function(element) {
3296+ return jqLiteInheritedData(element, '$injector');
3297+ },
3298+
3299+ removeAttr: function(element, name) {
3300+ element.removeAttribute(name);
3301+ },
3302+
3303+ hasClass: jqLiteHasClass,
3304+
3305+ css: function(element, name, value) {
3306+ name = camelCase(name);
3307+
3308+ if (isDefined(value)) {
3309+ element.style[name] = value;
3310+ } else {
3311+ return element.style[name];
3312+ }
3313+ },
3314+
3315+ attr: function(element, name, value) {
3316+ var nodeType = element.nodeType;
3317+ if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
3318+ return;
3319+ }
3320+ var lowercasedName = lowercase(name);
3321+ if (BOOLEAN_ATTR[lowercasedName]) {
3322+ if (isDefined(value)) {
3323+ if (!!value) {
3324+ element[name] = true;
3325+ element.setAttribute(name, lowercasedName);
3326+ } else {
3327+ element[name] = false;
3328+ element.removeAttribute(lowercasedName);
3329+ }
3330+ } else {
3331+ return (element[name] ||
3332+ (element.attributes.getNamedItem(name) || noop).specified)
3333+ ? lowercasedName
3334+ : undefined;
3335+ }
3336+ } else if (isDefined(value)) {
3337+ element.setAttribute(name, value);
3338+ } else if (element.getAttribute) {
3339+ // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
3340+ // some elements (e.g. Document) don't have get attribute, so return undefined
3341+ var ret = element.getAttribute(name, 2);
3342+ // normalize non-existing attributes to undefined (as jQuery)
3343+ return ret === null ? undefined : ret;
3344+ }
3345+ },
3346+
3347+ prop: function(element, name, value) {
3348+ if (isDefined(value)) {
3349+ element[name] = value;
3350+ } else {
3351+ return element[name];
3352+ }
3353+ },
3354+
3355+ text: (function() {
3356+ getText.$dv = '';
3357+ return getText;
3358+
3359+ function getText(element, value) {
3360+ if (isUndefined(value)) {
3361+ var nodeType = element.nodeType;
3362+ return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';
3363+ }
3364+ element.textContent = value;
3365+ }
3366+ })(),
3367+
3368+ val: function(element, value) {
3369+ if (isUndefined(value)) {
3370+ if (element.multiple && nodeName_(element) === 'select') {
3371+ var result = [];
3372+ forEach(element.options, function(option) {
3373+ if (option.selected) {
3374+ result.push(option.value || option.text);
3375+ }
3376+ });
3377+ return result.length === 0 ? null : result;
3378+ }
3379+ return element.value;
3380+ }
3381+ element.value = value;
3382+ },
3383+
3384+ html: function(element, value) {
3385+ if (isUndefined(value)) {
3386+ return element.innerHTML;
3387+ }
3388+ jqLiteDealoc(element, true);
3389+ element.innerHTML = value;
3390+ },
3391+
3392+ empty: jqLiteEmpty
3393+}, function(fn, name) {
3394+ /**
3395+ * Properties: writes return selection, reads return first value
3396+ */
3397+ JQLite.prototype[name] = function(arg1, arg2) {
3398+ var i, key;
3399+ var nodeCount = this.length;
3400+
3401+ // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
3402+ // in a way that survives minification.
3403+ // jqLiteEmpty takes no arguments but is a setter.
3404+ if (fn !== jqLiteEmpty &&
3405+ (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
3406+ if (isObject(arg1)) {
3407+
3408+ // we are a write, but the object properties are the key/values
3409+ for (i = 0; i < nodeCount; i++) {
3410+ if (fn === jqLiteData) {
3411+ // data() takes the whole object in jQuery
3412+ fn(this[i], arg1);
3413+ } else {
3414+ for (key in arg1) {
3415+ fn(this[i], key, arg1[key]);
3416+ }
3417+ }
3418+ }
3419+ // return self for chaining
3420+ return this;
3421+ } else {
3422+ // we are a read, so read the first child.
3423+ // TODO: do we still need this?
3424+ var value = fn.$dv;
3425+ // Only if we have $dv do we iterate over all, otherwise it is just the first element.
3426+ var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
3427+ for (var j = 0; j < jj; j++) {
3428+ var nodeValue = fn(this[j], arg1, arg2);
3429+ value = value ? value + nodeValue : nodeValue;
3430+ }
3431+ return value;
3432+ }
3433+ } else {
3434+ // we are a write, so apply to all children
3435+ for (i = 0; i < nodeCount; i++) {
3436+ fn(this[i], arg1, arg2);
3437+ }
3438+ // return self for chaining
3439+ return this;
3440+ }
3441+ };
3442+});
3443+
3444+function createEventHandler(element, events) {
3445+ var eventHandler = function(event, type) {
3446+ // jQuery specific api
3447+ event.isDefaultPrevented = function() {
3448+ return event.defaultPrevented;
3449+ };
3450+
3451+ var eventFns = events[type || event.type];
3452+ var eventFnsLength = eventFns ? eventFns.length : 0;
3453+
3454+ if (!eventFnsLength) return;
3455+
3456+ if (isUndefined(event.immediatePropagationStopped)) {
3457+ var originalStopImmediatePropagation = event.stopImmediatePropagation;
3458+ event.stopImmediatePropagation = function() {
3459+ event.immediatePropagationStopped = true;
3460+
3461+ if (event.stopPropagation) {
3462+ event.stopPropagation();
3463+ }
3464+
3465+ if (originalStopImmediatePropagation) {
3466+ originalStopImmediatePropagation.call(event);
3467+ }
3468+ };
3469+ }
3470+
3471+ event.isImmediatePropagationStopped = function() {
3472+ return event.immediatePropagationStopped === true;
3473+ };
3474+
3475+ // Some events have special handlers that wrap the real handler
3476+ var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;
3477+
3478+ // Copy event handlers in case event handlers array is modified during execution.
3479+ if ((eventFnsLength > 1)) {
3480+ eventFns = shallowCopy(eventFns);
3481+ }
3482+
3483+ for (var i = 0; i < eventFnsLength; i++) {
3484+ if (!event.isImmediatePropagationStopped()) {
3485+ handlerWrapper(element, event, eventFns[i]);
3486+ }
3487+ }
3488+ };
3489+
3490+ // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
3491+ // events on `element`
3492+ eventHandler.elem = element;
3493+ return eventHandler;
3494+}
3495+
3496+function defaultHandlerWrapper(element, event, handler) {
3497+ handler.call(element, event);
3498+}
3499+
3500+function specialMouseHandlerWrapper(target, event, handler) {
3501+ // Refer to jQuery's implementation of mouseenter & mouseleave
3502+ // Read about mouseenter and mouseleave:
3503+ // http://www.quirksmode.org/js/events_mouse.html#link8
3504+ var related = event.relatedTarget;
3505+ // For mousenter/leave call the handler if related is outside the target.
3506+ // NB: No relatedTarget if the mouse left/entered the browser window
3507+ if (!related || (related !== target && !jqLiteContains.call(target, related))) {
3508+ handler.call(target, event);
3509+ }
3510+}
3511+
3512+//////////////////////////////////////////
3513+// Functions iterating traversal.
3514+// These functions chain results into a single
3515+// selector.
3516+//////////////////////////////////////////
3517+forEach({
3518+ removeData: jqLiteRemoveData,
3519+
3520+ on: function jqLiteOn(element, type, fn, unsupported) {
3521+ if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
3522+
3523+ // Do not add event handlers to non-elements because they will not be cleaned up.
3524+ if (!jqLiteAcceptsData(element)) {
3525+ return;
3526+ }
3527+
3528+ var expandoStore = jqLiteExpandoStore(element, true);
3529+ var events = expandoStore.events;
3530+ var handle = expandoStore.handle;
3531+
3532+ if (!handle) {
3533+ handle = expandoStore.handle = createEventHandler(element, events);
3534+ }
3535+
3536+ // http://jsperf.com/string-indexof-vs-split
3537+ var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
3538+ var i = types.length;
3539+
3540+ var addHandler = function(type, specialHandlerWrapper, noEventListener) {
3541+ var eventFns = events[type];
3542+
3543+ if (!eventFns) {
3544+ eventFns = events[type] = [];
3545+ eventFns.specialHandlerWrapper = specialHandlerWrapper;
3546+ if (type !== '$destroy' && !noEventListener) {
3547+ addEventListenerFn(element, type, handle);
3548+ }
3549+ }
3550+
3551+ eventFns.push(fn);
3552+ };
3553+
3554+ while (i--) {
3555+ type = types[i];
3556+ if (MOUSE_EVENT_MAP[type]) {
3557+ addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
3558+ addHandler(type, undefined, true);
3559+ } else {
3560+ addHandler(type);
3561+ }
3562+ }
3563+ },
3564+
3565+ off: jqLiteOff,
3566+
3567+ one: function(element, type, fn) {
3568+ element = jqLite(element);
3569+
3570+ //add the listener twice so that when it is called
3571+ //you can remove the original function and still be
3572+ //able to call element.off(ev, fn) normally
3573+ element.on(type, function onFn() {
3574+ element.off(type, fn);
3575+ element.off(type, onFn);
3576+ });
3577+ element.on(type, fn);
3578+ },
3579+
3580+ replaceWith: function(element, replaceNode) {
3581+ var index, parent = element.parentNode;
3582+ jqLiteDealoc(element);
3583+ forEach(new JQLite(replaceNode), function(node) {
3584+ if (index) {
3585+ parent.insertBefore(node, index.nextSibling);
3586+ } else {
3587+ parent.replaceChild(node, element);
3588+ }
3589+ index = node;
3590+ });
3591+ },
3592+
3593+ children: function(element) {
3594+ var children = [];
3595+ forEach(element.childNodes, function(element) {
3596+ if (element.nodeType === NODE_TYPE_ELEMENT) {
3597+ children.push(element);
3598+ }
3599+ });
3600+ return children;
3601+ },
3602+
3603+ contents: function(element) {
3604+ return element.contentDocument || element.childNodes || [];
3605+ },
3606+
3607+ append: function(element, node) {
3608+ var nodeType = element.nodeType;
3609+ if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
3610+
3611+ node = new JQLite(node);
3612+
3613+ for (var i = 0, ii = node.length; i < ii; i++) {
3614+ var child = node[i];
3615+ element.appendChild(child);
3616+ }
3617+ },
3618+
3619+ prepend: function(element, node) {
3620+ if (element.nodeType === NODE_TYPE_ELEMENT) {
3621+ var index = element.firstChild;
3622+ forEach(new JQLite(node), function(child) {
3623+ element.insertBefore(child, index);
3624+ });
3625+ }
3626+ },
3627+
3628+ wrap: function(element, wrapNode) {
3629+ jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]);
3630+ },
3631+
3632+ remove: jqLiteRemove,
3633+
3634+ detach: function(element) {
3635+ jqLiteRemove(element, true);
3636+ },
3637+
3638+ after: function(element, newElement) {
3639+ var index = element, parent = element.parentNode;
3640+ newElement = new JQLite(newElement);
3641+
3642+ for (var i = 0, ii = newElement.length; i < ii; i++) {
3643+ var node = newElement[i];
3644+ parent.insertBefore(node, index.nextSibling);
3645+ index = node;
3646+ }
3647+ },
3648+
3649+ addClass: jqLiteAddClass,
3650+ removeClass: jqLiteRemoveClass,
3651+
3652+ toggleClass: function(element, selector, condition) {
3653+ if (selector) {
3654+ forEach(selector.split(' '), function(className) {
3655+ var classCondition = condition;
3656+ if (isUndefined(classCondition)) {
3657+ classCondition = !jqLiteHasClass(element, className);
3658+ }
3659+ (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
3660+ });
3661+ }
3662+ },
3663+
3664+ parent: function(element) {
3665+ var parent = element.parentNode;
3666+ return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;
3667+ },
3668+
3669+ next: function(element) {
3670+ return element.nextElementSibling;
3671+ },
3672+
3673+ find: function(element, selector) {
3674+ if (element.getElementsByTagName) {
3675+ return element.getElementsByTagName(selector);
3676+ } else {
3677+ return [];
3678+ }
3679+ },
3680+
3681+ clone: jqLiteClone,
3682+
3683+ triggerHandler: function(element, event, extraParameters) {
3684+
3685+ var dummyEvent, eventFnsCopy, handlerArgs;
3686+ var eventName = event.type || event;
3687+ var expandoStore = jqLiteExpandoStore(element);
3688+ var events = expandoStore && expandoStore.events;
3689+ var eventFns = events && events[eventName];
3690+
3691+ if (eventFns) {
3692+ // Create a dummy event to pass to the handlers
3693+ dummyEvent = {
3694+ preventDefault: function() { this.defaultPrevented = true; },
3695+ isDefaultPrevented: function() { return this.defaultPrevented === true; },
3696+ stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
3697+ isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
3698+ stopPropagation: noop,
3699+ type: eventName,
3700+ target: element
3701+ };
3702+
3703+ // If a custom event was provided then extend our dummy event with it
3704+ if (event.type) {
3705+ dummyEvent = extend(dummyEvent, event);
3706+ }
3707+
3708+ // Copy event handlers in case event handlers array is modified during execution.
3709+ eventFnsCopy = shallowCopy(eventFns);
3710+ handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
3711+
3712+ forEach(eventFnsCopy, function(fn) {
3713+ if (!dummyEvent.isImmediatePropagationStopped()) {
3714+ fn.apply(element, handlerArgs);
3715+ }
3716+ });
3717+ }
3718+ }
3719+}, function(fn, name) {
3720+ /**
3721+ * chaining functions
3722+ */
3723+ JQLite.prototype[name] = function(arg1, arg2, arg3) {
3724+ var value;
3725+
3726+ for (var i = 0, ii = this.length; i < ii; i++) {
3727+ if (isUndefined(value)) {
3728+ value = fn(this[i], arg1, arg2, arg3);
3729+ if (isDefined(value)) {
3730+ // any function which returns a value needs to be wrapped
3731+ value = jqLite(value);
3732+ }
3733+ } else {
3734+ jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
3735+ }
3736+ }
3737+ return isDefined(value) ? value : this;
3738+ };
3739+
3740+ // bind legacy bind/unbind to on/off
3741+ JQLite.prototype.bind = JQLite.prototype.on;
3742+ JQLite.prototype.unbind = JQLite.prototype.off;
3743+});
3744+
3745+
3746+// Provider for private $$jqLite service
3747+function $$jqLiteProvider() {
3748+ this.$get = function $$jqLite() {
3749+ return extend(JQLite, {
3750+ hasClass: function(node, classes) {
3751+ if (node.attr) node = node[0];
3752+ return jqLiteHasClass(node, classes);
3753+ },
3754+ addClass: function(node, classes) {
3755+ if (node.attr) node = node[0];
3756+ return jqLiteAddClass(node, classes);
3757+ },
3758+ removeClass: function(node, classes) {
3759+ if (node.attr) node = node[0];
3760+ return jqLiteRemoveClass(node, classes);
3761+ }
3762+ });
3763+ };
3764+}
3765+
3766+/**
3767+ * Computes a hash of an 'obj'.
3768+ * Hash of a:
3769+ * string is string
3770+ * number is number as string
3771+ * object is either result of calling $$hashKey function on the object or uniquely generated id,
3772+ * that is also assigned to the $$hashKey property of the object.
3773+ *
3774+ * @param obj
3775+ * @returns {string} hash string such that the same input will have the same hash string.
3776+ * The resulting string key is in 'type:hashKey' format.
3777+ */
3778+function hashKey(obj, nextUidFn) {
3779+ var key = obj && obj.$$hashKey;
3780+
3781+ if (key) {
3782+ if (typeof key === 'function') {
3783+ key = obj.$$hashKey();
3784+ }
3785+ return key;
3786+ }
3787+
3788+ var objType = typeof obj;
3789+ if (objType == 'function' || (objType == 'object' && obj !== null)) {
3790+ key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();
3791+ } else {
3792+ key = objType + ':' + obj;
3793+ }
3794+
3795+ return key;
3796+}
3797+
3798+/**
3799+ * HashMap which can use objects as keys
3800+ */
3801+function HashMap(array, isolatedUid) {
3802+ if (isolatedUid) {
3803+ var uid = 0;
3804+ this.nextUid = function() {
3805+ return ++uid;
3806+ };
3807+ }
3808+ forEach(array, this.put, this);
3809+}
3810+HashMap.prototype = {
3811+ /**
3812+ * Store key value pair
3813+ * @param key key to store can be any type
3814+ * @param value value to store can be any type
3815+ */
3816+ put: function(key, value) {
3817+ this[hashKey(key, this.nextUid)] = value;
3818+ },
3819+
3820+ /**
3821+ * @param key
3822+ * @returns {Object} the value for the key
3823+ */
3824+ get: function(key) {
3825+ return this[hashKey(key, this.nextUid)];
3826+ },
3827+
3828+ /**
3829+ * Remove the key/value pair
3830+ * @param key
3831+ */
3832+ remove: function(key) {
3833+ var value = this[key = hashKey(key, this.nextUid)];
3834+ delete this[key];
3835+ return value;
3836+ }
3837+};
3838+
3839+var $$HashMapProvider = [function() {
3840+ this.$get = [function() {
3841+ return HashMap;
3842+ }];
3843+}];
3844+
3845+/**
3846+ * @ngdoc function
3847+ * @module ng
3848+ * @name angular.injector
3849+ * @kind function
3850+ *
3851+ * @description
3852+ * Creates an injector object that can be used for retrieving services as well as for
3853+ * dependency injection (see {@link guide/di dependency injection}).
3854+ *
3855+ * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
3856+ * {@link angular.module}. The `ng` module must be explicitly added.
3857+ * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
3858+ * disallows argument name annotation inference.
3859+ * @returns {injector} Injector object. See {@link auto.$injector $injector}.
3860+ *
3861+ * @example
3862+ * Typical usage
3863+ * ```js
3864+ * // create an injector
3865+ * var $injector = angular.injector(['ng']);
3866+ *
3867+ * // use the injector to kick off your application
3868+ * // use the type inference to auto inject arguments, or use implicit injection
3869+ * $injector.invoke(function($rootScope, $compile, $document) {
3870+ * $compile($document)($rootScope);
3871+ * $rootScope.$digest();
3872+ * });
3873+ * ```
3874+ *
3875+ * Sometimes you want to get access to the injector of a currently running Angular app
3876+ * from outside Angular. Perhaps, you want to inject and compile some markup after the
3877+ * application has been bootstrapped. You can do this using the extra `injector()` added
3878+ * to JQuery/jqLite elements. See {@link angular.element}.
3879+ *
3880+ * *This is fairly rare but could be the case if a third party library is injecting the
3881+ * markup.*
3882+ *
3883+ * In the following example a new block of HTML containing a `ng-controller`
3884+ * directive is added to the end of the document body by JQuery. We then compile and link
3885+ * it into the current AngularJS scope.
3886+ *
3887+ * ```js
3888+ * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
3889+ * $(document.body).append($div);
3890+ *
3891+ * angular.element(document).injector().invoke(function($compile) {
3892+ * var scope = angular.element($div).scope();
3893+ * $compile($div)(scope);
3894+ * });
3895+ * ```
3896+ */
3897+
3898+
3899+/**
3900+ * @ngdoc module
3901+ * @name auto
3902+ * @installation
3903+ * @description
3904+ *
3905+ * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
3906+ */
3907+
3908+var ARROW_ARG = /^([^\(]+?)=>/;
3909+var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
3910+var FN_ARG_SPLIT = /,/;
3911+var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
3912+var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
3913+var $injectorMinErr = minErr('$injector');
3914+
3915+function stringifyFn(fn) {
3916+ // Support: Chrome 50-51 only
3917+ // Creating a new string by adding `' '` at the end, to hack around some bug in Chrome v50/51
3918+ // (See https://github.com/angular/angular.js/issues/14487.)
3919+ // TODO (gkalpak): Remove workaround when Chrome v52 is released
3920+ return Function.prototype.toString.call(fn) + ' ';
3921+}
3922+
3923+function extractArgs(fn) {
3924+ var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''),
3925+ args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
3926+ return args;
3927+}
3928+
3929+function anonFn(fn) {
3930+ // For anonymous functions, showing at the very least the function signature can help in
3931+ // debugging.
3932+ var args = extractArgs(fn);
3933+ if (args) {
3934+ return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
3935+ }
3936+ return 'fn';
3937+}
3938+
3939+function annotate(fn, strictDi, name) {
3940+ var $inject,
3941+ argDecl,
3942+ last;
3943+
3944+ if (typeof fn === 'function') {
3945+ if (!($inject = fn.$inject)) {
3946+ $inject = [];
3947+ if (fn.length) {
3948+ if (strictDi) {
3949+ if (!isString(name) || !name) {
3950+ name = fn.name || anonFn(fn);
3951+ }
3952+ throw $injectorMinErr('strictdi',
3953+ '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
3954+ }
3955+ argDecl = extractArgs(fn);
3956+ forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
3957+ arg.replace(FN_ARG, function(all, underscore, name) {
3958+ $inject.push(name);
3959+ });
3960+ });
3961+ }
3962+ fn.$inject = $inject;
3963+ }
3964+ } else if (isArray(fn)) {
3965+ last = fn.length - 1;
3966+ assertArgFn(fn[last], 'fn');
3967+ $inject = fn.slice(0, last);
3968+ } else {
3969+ assertArgFn(fn, 'fn', true);
3970+ }
3971+ return $inject;
3972+}
3973+
3974+///////////////////////////////////////
3975+
3976+/**
3977+ * @ngdoc service
3978+ * @name $injector
3979+ *
3980+ * @description
3981+ *
3982+ * `$injector` is used to retrieve object instances as defined by
3983+ * {@link auto.$provide provider}, instantiate types, invoke methods,
3984+ * and load modules.
3985+ *
3986+ * The following always holds true:
3987+ *
3988+ * ```js
3989+ * var $injector = angular.injector();
3990+ * expect($injector.get('$injector')).toBe($injector);
3991+ * expect($injector.invoke(function($injector) {
3992+ * return $injector;
3993+ * })).toBe($injector);
3994+ * ```
3995+ *
3996+ * # Injection Function Annotation
3997+ *
3998+ * JavaScript does not have annotations, and annotations are needed for dependency injection. The
3999+ * following are all valid ways of annotating function with injection arguments and are equivalent.
4000+ *
4001+ * ```js
4002+ * // inferred (only works if code not minified/obfuscated)
4003+ * $injector.invoke(function(serviceA){});
4004+ *
4005+ * // annotated
4006+ * function explicit(serviceA) {};
4007+ * explicit.$inject = ['serviceA'];
4008+ * $injector.invoke(explicit);
4009+ *
4010+ * // inline
4011+ * $injector.invoke(['serviceA', function(serviceA){}]);
4012+ * ```
4013+ *
4014+ * ## Inference
4015+ *
4016+ * In JavaScript calling `toString()` on a function returns the function definition. The definition
4017+ * can then be parsed and the function arguments can be extracted. This method of discovering
4018+ * annotations is disallowed when the injector is in strict mode.
4019+ * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
4020+ * argument names.
4021+ *
4022+ * ## `$inject` Annotation
4023+ * By adding an `$inject` property onto a function the injection parameters can be specified.
4024+ *
4025+ * ## Inline
4026+ * As an array of injection names, where the last item in the array is the function to call.
4027+ */
4028+
4029+/**
4030+ * @ngdoc method
4031+ * @name $injector#get
4032+ *
4033+ * @description
4034+ * Return an instance of the service.
4035+ *
4036+ * @param {string} name The name of the instance to retrieve.
4037+ * @param {string=} caller An optional string to provide the origin of the function call for error messages.
4038+ * @return {*} The instance.
4039+ */
4040+
4041+/**
4042+ * @ngdoc method
4043+ * @name $injector#invoke
4044+ *
4045+ * @description
4046+ * Invoke the method and supply the method arguments from the `$injector`.
4047+ *
4048+ * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
4049+ * injected according to the {@link guide/di $inject Annotation} rules.
4050+ * @param {Object=} self The `this` for the invoked method.
4051+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
4052+ * object first, before the `$injector` is consulted.
4053+ * @returns {*} the value returned by the invoked `fn` function.
4054+ */
4055+
4056+/**
4057+ * @ngdoc method
4058+ * @name $injector#has
4059+ *
4060+ * @description
4061+ * Allows the user to query if the particular service exists.
4062+ *
4063+ * @param {string} name Name of the service to query.
4064+ * @returns {boolean} `true` if injector has given service.
4065+ */
4066+
4067+/**
4068+ * @ngdoc method
4069+ * @name $injector#instantiate
4070+ * @description
4071+ * Create a new instance of JS type. The method takes a constructor function, invokes the new
4072+ * operator, and supplies all of the arguments to the constructor function as specified by the
4073+ * constructor annotation.
4074+ *
4075+ * @param {Function} Type Annotated constructor function.
4076+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
4077+ * object first, before the `$injector` is consulted.
4078+ * @returns {Object} new instance of `Type`.
4079+ */
4080+
4081+/**
4082+ * @ngdoc method
4083+ * @name $injector#annotate
4084+ *
4085+ * @description
4086+ * Returns an array of service names which the function is requesting for injection. This API is
4087+ * used by the injector to determine which services need to be injected into the function when the
4088+ * function is invoked. There are three ways in which the function can be annotated with the needed
4089+ * dependencies.
4090+ *
4091+ * # Argument names
4092+ *
4093+ * The simplest form is to extract the dependencies from the arguments of the function. This is done
4094+ * by converting the function into a string using `toString()` method and extracting the argument
4095+ * names.
4096+ * ```js
4097+ * // Given
4098+ * function MyController($scope, $route) {
4099+ * // ...
4100+ * }
4101+ *
4102+ * // Then
4103+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
4104+ * ```
4105+ *
4106+ * You can disallow this method by using strict injection mode.
4107+ *
4108+ * This method does not work with code minification / obfuscation. For this reason the following
4109+ * annotation strategies are supported.
4110+ *
4111+ * # The `$inject` property
4112+ *
4113+ * If a function has an `$inject` property and its value is an array of strings, then the strings
4114+ * represent names of services to be injected into the function.
4115+ * ```js
4116+ * // Given
4117+ * var MyController = function(obfuscatedScope, obfuscatedRoute) {
4118+ * // ...
4119+ * }
4120+ * // Define function dependencies
4121+ * MyController['$inject'] = ['$scope', '$route'];
4122+ *
4123+ * // Then
4124+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
4125+ * ```
4126+ *
4127+ * # The array notation
4128+ *
4129+ * It is often desirable to inline Injected functions and that's when setting the `$inject` property
4130+ * is very inconvenient. In these situations using the array notation to specify the dependencies in
4131+ * a way that survives minification is a better choice:
4132+ *
4133+ * ```js
4134+ * // We wish to write this (not minification / obfuscation safe)
4135+ * injector.invoke(function($compile, $rootScope) {
4136+ * // ...
4137+ * });
4138+ *
4139+ * // We are forced to write break inlining
4140+ * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
4141+ * // ...
4142+ * };
4143+ * tmpFn.$inject = ['$compile', '$rootScope'];
4144+ * injector.invoke(tmpFn);
4145+ *
4146+ * // To better support inline function the inline annotation is supported
4147+ * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
4148+ * // ...
4149+ * }]);
4150+ *
4151+ * // Therefore
4152+ * expect(injector.annotate(
4153+ * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
4154+ * ).toEqual(['$compile', '$rootScope']);
4155+ * ```
4156+ *
4157+ * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
4158+ * be retrieved as described above.
4159+ *
4160+ * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
4161+ *
4162+ * @returns {Array.<string>} The names of the services which the function requires.
4163+ */
4164+
4165+
4166+
4167+
4168+/**
4169+ * @ngdoc service
4170+ * @name $provide
4171+ *
4172+ * @description
4173+ *
4174+ * The {@link auto.$provide $provide} service has a number of methods for registering components
4175+ * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
4176+ * {@link angular.Module}.
4177+ *
4178+ * An Angular **service** is a singleton object created by a **service factory**. These **service
4179+ * factories** are functions which, in turn, are created by a **service provider**.
4180+ * The **service providers** are constructor functions. When instantiated they must contain a
4181+ * property called `$get`, which holds the **service factory** function.
4182+ *
4183+ * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
4184+ * correct **service provider**, instantiating it and then calling its `$get` **service factory**
4185+ * function to get the instance of the **service**.
4186+ *
4187+ * Often services have no configuration options and there is no need to add methods to the service
4188+ * provider. The provider will be no more than a constructor function with a `$get` property. For
4189+ * these cases the {@link auto.$provide $provide} service has additional helper methods to register
4190+ * services without specifying a provider.
4191+ *
4192+ * * {@link auto.$provide#provider provider(name, provider)} - registers a **service provider** with the
4193+ * {@link auto.$injector $injector}
4194+ * * {@link auto.$provide#constant constant(name, obj)} - registers a value/object that can be accessed by
4195+ * providers and services.
4196+ * * {@link auto.$provide#value value(name, obj)} - registers a value/object that can only be accessed by
4197+ * services, not providers.
4198+ * * {@link auto.$provide#factory factory(name, fn)} - registers a service **factory function**
4199+ * that will be wrapped in a **service provider** object, whose `$get` property will contain the
4200+ * given factory function.
4201+ * * {@link auto.$provide#service service(name, Fn)} - registers a **constructor function**
4202+ * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
4203+ * a new object using the given constructor function.
4204+ * * {@link auto.$provide#decorator decorator(name, decorFn)} - registers a **decorator function** that
4205+ * will be able to modify or replace the implementation of another service.
4206+ *
4207+ * See the individual methods for more information and examples.
4208+ */
4209+
4210+/**
4211+ * @ngdoc method
4212+ * @name $provide#provider
4213+ * @description
4214+ *
4215+ * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
4216+ * are constructor functions, whose instances are responsible for "providing" a factory for a
4217+ * service.
4218+ *
4219+ * Service provider names start with the name of the service they provide followed by `Provider`.
4220+ * For example, the {@link ng.$log $log} service has a provider called
4221+ * {@link ng.$logProvider $logProvider}.
4222+ *
4223+ * Service provider objects can have additional methods which allow configuration of the provider
4224+ * and its service. Importantly, you can configure what kind of service is created by the `$get`
4225+ * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
4226+ * method {@link ng.$logProvider#debugEnabled debugEnabled}
4227+ * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
4228+ * console or not.
4229+ *
4230+ * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
4231+ 'Provider'` key.
4232+ * @param {(Object|function())} provider If the provider is:
4233+ *
4234+ * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
4235+ * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
4236+ * - `Constructor`: a new instance of the provider will be created using
4237+ * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
4238+ *
4239+ * @returns {Object} registered provider instance
4240+
4241+ * @example
4242+ *
4243+ * The following example shows how to create a simple event tracking service and register it using
4244+ * {@link auto.$provide#provider $provide.provider()}.
4245+ *
4246+ * ```js
4247+ * // Define the eventTracker provider
4248+ * function EventTrackerProvider() {
4249+ * var trackingUrl = '/track';
4250+ *
4251+ * // A provider method for configuring where the tracked events should been saved
4252+ * this.setTrackingUrl = function(url) {
4253+ * trackingUrl = url;
4254+ * };
4255+ *
4256+ * // The service factory function
4257+ * this.$get = ['$http', function($http) {
4258+ * var trackedEvents = {};
4259+ * return {
4260+ * // Call this to track an event
4261+ * event: function(event) {
4262+ * var count = trackedEvents[event] || 0;
4263+ * count += 1;
4264+ * trackedEvents[event] = count;
4265+ * return count;
4266+ * },
4267+ * // Call this to save the tracked events to the trackingUrl
4268+ * save: function() {
4269+ * $http.post(trackingUrl, trackedEvents);
4270+ * }
4271+ * };
4272+ * }];
4273+ * }
4274+ *
4275+ * describe('eventTracker', function() {
4276+ * var postSpy;
4277+ *
4278+ * beforeEach(module(function($provide) {
4279+ * // Register the eventTracker provider
4280+ * $provide.provider('eventTracker', EventTrackerProvider);
4281+ * }));
4282+ *
4283+ * beforeEach(module(function(eventTrackerProvider) {
4284+ * // Configure eventTracker provider
4285+ * eventTrackerProvider.setTrackingUrl('/custom-track');
4286+ * }));
4287+ *
4288+ * it('tracks events', inject(function(eventTracker) {
4289+ * expect(eventTracker.event('login')).toEqual(1);
4290+ * expect(eventTracker.event('login')).toEqual(2);
4291+ * }));
4292+ *
4293+ * it('saves to the tracking url', inject(function(eventTracker, $http) {
4294+ * postSpy = spyOn($http, 'post');
4295+ * eventTracker.event('login');
4296+ * eventTracker.save();
4297+ * expect(postSpy).toHaveBeenCalled();
4298+ * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
4299+ * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
4300+ * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
4301+ * }));
4302+ * });
4303+ * ```
4304+ */
4305+
4306+/**
4307+ * @ngdoc method
4308+ * @name $provide#factory
4309+ * @description
4310+ *
4311+ * Register a **service factory**, which will be called to return the service instance.
4312+ * This is short for registering a service where its provider consists of only a `$get` property,
4313+ * which is the given service factory function.
4314+ * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
4315+ * configure your service in a provider.
4316+ *
4317+ * @param {string} name The name of the instance.
4318+ * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
4319+ * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
4320+ * @returns {Object} registered provider instance
4321+ *
4322+ * @example
4323+ * Here is an example of registering a service
4324+ * ```js
4325+ * $provide.factory('ping', ['$http', function($http) {
4326+ * return function ping() {
4327+ * return $http.send('/ping');
4328+ * };
4329+ * }]);
4330+ * ```
4331+ * You would then inject and use this service like this:
4332+ * ```js
4333+ * someModule.controller('Ctrl', ['ping', function(ping) {
4334+ * ping();
4335+ * }]);
4336+ * ```
4337+ */
4338+
4339+
4340+/**
4341+ * @ngdoc method
4342+ * @name $provide#service
4343+ * @description
4344+ *
4345+ * Register a **service constructor**, which will be invoked with `new` to create the service
4346+ * instance.
4347+ * This is short for registering a service where its provider's `$get` property is a factory
4348+ * function that returns an instance instantiated by the injector from the service constructor
4349+ * function.
4350+ *
4351+ * Internally it looks a bit like this:
4352+ *
4353+ * ```
4354+ * {
4355+ * $get: function() {
4356+ * return $injector.instantiate(constructor);
4357+ * }
4358+ * }
4359+ * ```
4360+ *
4361+ *
4362+ * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
4363+ * as a type/class.
4364+ *
4365+ * @param {string} name The name of the instance.
4366+ * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
4367+ * that will be instantiated.
4368+ * @returns {Object} registered provider instance
4369+ *
4370+ * @example
4371+ * Here is an example of registering a service using
4372+ * {@link auto.$provide#service $provide.service(class)}.
4373+ * ```js
4374+ * var Ping = function($http) {
4375+ * this.$http = $http;
4376+ * };
4377+ *
4378+ * Ping.$inject = ['$http'];
4379+ *
4380+ * Ping.prototype.send = function() {
4381+ * return this.$http.get('/ping');
4382+ * };
4383+ * $provide.service('ping', Ping);
4384+ * ```
4385+ * You would then inject and use this service like this:
4386+ * ```js
4387+ * someModule.controller('Ctrl', ['ping', function(ping) {
4388+ * ping.send();
4389+ * }]);
4390+ * ```
4391+ */
4392+
4393+
4394+/**
4395+ * @ngdoc method
4396+ * @name $provide#value
4397+ * @description
4398+ *
4399+ * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
4400+ * number, an array, an object or a function. This is short for registering a service where its
4401+ * provider's `$get` property is a factory function that takes no arguments and returns the **value
4402+ * service**. That also means it is not possible to inject other services into a value service.
4403+ *
4404+ * Value services are similar to constant services, except that they cannot be injected into a
4405+ * module configuration function (see {@link angular.Module#config}) but they can be overridden by
4406+ * an Angular {@link auto.$provide#decorator decorator}.
4407+ *
4408+ * @param {string} name The name of the instance.
4409+ * @param {*} value The value.
4410+ * @returns {Object} registered provider instance
4411+ *
4412+ * @example
4413+ * Here are some examples of creating value services.
4414+ * ```js
4415+ * $provide.value('ADMIN_USER', 'admin');
4416+ *
4417+ * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
4418+ *
4419+ * $provide.value('halfOf', function(value) {
4420+ * return value / 2;
4421+ * });
4422+ * ```
4423+ */
4424+
4425+
4426+/**
4427+ * @ngdoc method
4428+ * @name $provide#constant
4429+ * @description
4430+ *
4431+ * Register a **constant service** with the {@link auto.$injector $injector}, such as a string,
4432+ * a number, an array, an object or a function. Like the {@link auto.$provide#value value}, it is not
4433+ * possible to inject other services into a constant.
4434+ *
4435+ * But unlike {@link auto.$provide#value value}, a constant can be
4436+ * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
4437+ * be overridden by an Angular {@link auto.$provide#decorator decorator}.
4438+ *
4439+ * @param {string} name The name of the constant.
4440+ * @param {*} value The constant value.
4441+ * @returns {Object} registered instance
4442+ *
4443+ * @example
4444+ * Here a some examples of creating constants:
4445+ * ```js
4446+ * $provide.constant('SHARD_HEIGHT', 306);
4447+ *
4448+ * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
4449+ *
4450+ * $provide.constant('double', function(value) {
4451+ * return value * 2;
4452+ * });
4453+ * ```
4454+ */
4455+
4456+
4457+/**
4458+ * @ngdoc method
4459+ * @name $provide#decorator
4460+ * @description
4461+ *
4462+ * Register a **decorator function** with the {@link auto.$injector $injector}. A decorator function
4463+ * intercepts the creation of a service, allowing it to override or modify the behavior of the
4464+ * service. The return value of the decorator function may be the original service, or a new service
4465+ * that replaces (or wraps and delegates to) the original service.
4466+ *
4467+ * You can find out more about using decorators in the {@link guide/decorators} guide.
4468+ *
4469+ * @param {string} name The name of the service to decorate.
4470+ * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
4471+ * provided and should return the decorated service instance. The function is called using
4472+ * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
4473+ * Local injection arguments:
4474+ *
4475+ * * `$delegate` - The original service instance, which can be replaced, monkey patched, configured,
4476+ * decorated or delegated to.
4477+ *
4478+ * @example
4479+ * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
4480+ * calls to {@link ng.$log#error $log.warn()}.
4481+ * ```js
4482+ * $provide.decorator('$log', ['$delegate', function($delegate) {
4483+ * $delegate.warn = $delegate.error;
4484+ * return $delegate;
4485+ * }]);
4486+ * ```
4487+ */
4488+
4489+
4490+function createInjector(modulesToLoad, strictDi) {
4491+ strictDi = (strictDi === true);
4492+ var INSTANTIATING = {},
4493+ providerSuffix = 'Provider',
4494+ path = [],
4495+ loadedModules = new HashMap([], true),
4496+ providerCache = {
4497+ $provide: {
4498+ provider: supportObject(provider),
4499+ factory: supportObject(factory),
4500+ service: supportObject(service),
4501+ value: supportObject(value),
4502+ constant: supportObject(constant),
4503+ decorator: decorator
4504+ }
4505+ },
4506+ providerInjector = (providerCache.$injector =
4507+ createInternalInjector(providerCache, function(serviceName, caller) {
4508+ if (angular.isString(caller)) {
4509+ path.push(caller);
4510+ }
4511+ throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
4512+ })),
4513+ instanceCache = {},
4514+ protoInstanceInjector =
4515+ createInternalInjector(instanceCache, function(serviceName, caller) {
4516+ var provider = providerInjector.get(serviceName + providerSuffix, caller);
4517+ return instanceInjector.invoke(
4518+ provider.$get, provider, undefined, serviceName);
4519+ }),
4520+ instanceInjector = protoInstanceInjector;
4521+
4522+ providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) };
4523+ var runBlocks = loadModules(modulesToLoad);
4524+ instanceInjector = protoInstanceInjector.get('$injector');
4525+ instanceInjector.strictDi = strictDi;
4526+ forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); });
4527+
4528+ return instanceInjector;
4529+
4530+ ////////////////////////////////////
4531+ // $provider
4532+ ////////////////////////////////////
4533+
4534+ function supportObject(delegate) {
4535+ return function(key, value) {
4536+ if (isObject(key)) {
4537+ forEach(key, reverseParams(delegate));
4538+ } else {
4539+ return delegate(key, value);
4540+ }
4541+ };
4542+ }
4543+
4544+ function provider(name, provider_) {
4545+ assertNotHasOwnProperty(name, 'service');
4546+ if (isFunction(provider_) || isArray(provider_)) {
4547+ provider_ = providerInjector.instantiate(provider_);
4548+ }
4549+ if (!provider_.$get) {
4550+ throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
4551+ }
4552+ return providerCache[name + providerSuffix] = provider_;
4553+ }
4554+
4555+ function enforceReturnValue(name, factory) {
4556+ return function enforcedReturnValue() {
4557+ var result = instanceInjector.invoke(factory, this);
4558+ if (isUndefined(result)) {
4559+ throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
4560+ }
4561+ return result;
4562+ };
4563+ }
4564+
4565+ function factory(name, factoryFn, enforce) {
4566+ return provider(name, {
4567+ $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
4568+ });
4569+ }
4570+
4571+ function service(name, constructor) {
4572+ return factory(name, ['$injector', function($injector) {
4573+ return $injector.instantiate(constructor);
4574+ }]);
4575+ }
4576+
4577+ function value(name, val) { return factory(name, valueFn(val), false); }
4578+
4579+ function constant(name, value) {
4580+ assertNotHasOwnProperty(name, 'constant');
4581+ providerCache[name] = value;
4582+ instanceCache[name] = value;
4583+ }
4584+
4585+ function decorator(serviceName, decorFn) {
4586+ var origProvider = providerInjector.get(serviceName + providerSuffix),
4587+ orig$get = origProvider.$get;
4588+
4589+ origProvider.$get = function() {
4590+ var origInstance = instanceInjector.invoke(orig$get, origProvider);
4591+ return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
4592+ };
4593+ }
4594+
4595+ ////////////////////////////////////
4596+ // Module Loading
4597+ ////////////////////////////////////
4598+ function loadModules(modulesToLoad) {
4599+ assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');
4600+ var runBlocks = [], moduleFn;
4601+ forEach(modulesToLoad, function(module) {
4602+ if (loadedModules.get(module)) return;
4603+ loadedModules.put(module, true);
4604+
4605+ function runInvokeQueue(queue) {
4606+ var i, ii;
4607+ for (i = 0, ii = queue.length; i < ii; i++) {
4608+ var invokeArgs = queue[i],
4609+ provider = providerInjector.get(invokeArgs[0]);
4610+
4611+ provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
4612+ }
4613+ }
4614+
4615+ try {
4616+ if (isString(module)) {
4617+ moduleFn = angularModule(module);
4618+ runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
4619+ runInvokeQueue(moduleFn._invokeQueue);
4620+ runInvokeQueue(moduleFn._configBlocks);
4621+ } else if (isFunction(module)) {
4622+ runBlocks.push(providerInjector.invoke(module));
4623+ } else if (isArray(module)) {
4624+ runBlocks.push(providerInjector.invoke(module));
4625+ } else {
4626+ assertArgFn(module, 'module');
4627+ }
4628+ } catch (e) {
4629+ if (isArray(module)) {
4630+ module = module[module.length - 1];
4631+ }
4632+ if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
4633+ // Safari & FF's stack traces don't contain error.message content
4634+ // unlike those of Chrome and IE
4635+ // So if stack doesn't contain message, we create a new string that contains both.
4636+ // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
4637+ /* jshint -W022 */
4638+ e = e.message + '\n' + e.stack;
4639+ }
4640+ throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
4641+ module, e.stack || e.message || e);
4642+ }
4643+ });
4644+ return runBlocks;
4645+ }
4646+
4647+ ////////////////////////////////////
4648+ // internal Injector
4649+ ////////////////////////////////////
4650+
4651+ function createInternalInjector(cache, factory) {
4652+
4653+ function getService(serviceName, caller) {
4654+ if (cache.hasOwnProperty(serviceName)) {
4655+ if (cache[serviceName] === INSTANTIATING) {
4656+ throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
4657+ serviceName + ' <- ' + path.join(' <- '));
4658+ }
4659+ return cache[serviceName];
4660+ } else {
4661+ try {
4662+ path.unshift(serviceName);
4663+ cache[serviceName] = INSTANTIATING;
4664+ return cache[serviceName] = factory(serviceName, caller);
4665+ } catch (err) {
4666+ if (cache[serviceName] === INSTANTIATING) {
4667+ delete cache[serviceName];
4668+ }
4669+ throw err;
4670+ } finally {
4671+ path.shift();
4672+ }
4673+ }
4674+ }
4675+
4676+
4677+ function injectionArgs(fn, locals, serviceName) {
4678+ var args = [],
4679+ $inject = createInjector.$$annotate(fn, strictDi, serviceName);
4680+
4681+ for (var i = 0, length = $inject.length; i < length; i++) {
4682+ var key = $inject[i];
4683+ if (typeof key !== 'string') {
4684+ throw $injectorMinErr('itkn',
4685+ 'Incorrect injection token! Expected service name as string, got {0}', key);
4686+ }
4687+ args.push(locals && locals.hasOwnProperty(key) ? locals[key] :
4688+ getService(key, serviceName));
4689+ }
4690+ return args;
4691+ }
4692+
4693+ function isClass(func) {
4694+ // IE 9-11 do not support classes and IE9 leaks with the code below.
4695+ if (msie <= 11) {
4696+ return false;
4697+ }
4698+ // Support: Edge 12-13 only
4699+ // See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6156135/
4700+ return typeof func === 'function'
4701+ && /^(?:class\b|constructor\()/.test(stringifyFn(func));
4702+ }
4703+
4704+ function invoke(fn, self, locals, serviceName) {
4705+ if (typeof locals === 'string') {
4706+ serviceName = locals;
4707+ locals = null;
4708+ }
4709+
4710+ var args = injectionArgs(fn, locals, serviceName);
4711+ if (isArray(fn)) {
4712+ fn = fn[fn.length - 1];
4713+ }
4714+
4715+ if (!isClass(fn)) {
4716+ // http://jsperf.com/angularjs-invoke-apply-vs-switch
4717+ // #5388
4718+ return fn.apply(self, args);
4719+ } else {
4720+ args.unshift(null);
4721+ return new (Function.prototype.bind.apply(fn, args))();
4722+ }
4723+ }
4724+
4725+
4726+ function instantiate(Type, locals, serviceName) {
4727+ // Check if Type is annotated and use just the given function at n-1 as parameter
4728+ // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
4729+ var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
4730+ var args = injectionArgs(Type, locals, serviceName);
4731+ // Empty object at position 0 is ignored for invocation with `new`, but required.
4732+ args.unshift(null);
4733+ return new (Function.prototype.bind.apply(ctor, args))();
4734+ }
4735+
4736+
4737+ return {
4738+ invoke: invoke,
4739+ instantiate: instantiate,
4740+ get: getService,
4741+ annotate: createInjector.$$annotate,
4742+ has: function(name) {
4743+ return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
4744+ }
4745+ };
4746+ }
4747+}
4748+
4749+createInjector.$$annotate = annotate;
4750+
4751+/**
4752+ * @ngdoc provider
4753+ * @name $anchorScrollProvider
4754+ *
4755+ * @description
4756+ * Use `$anchorScrollProvider` to disable automatic scrolling whenever
4757+ * {@link ng.$location#hash $location.hash()} changes.
4758+ */
4759+function $AnchorScrollProvider() {
4760+
4761+ var autoScrollingEnabled = true;
4762+
4763+ /**
4764+ * @ngdoc method
4765+ * @name $anchorScrollProvider#disableAutoScrolling
4766+ *
4767+ * @description
4768+ * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
4769+ * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
4770+ * Use this method to disable automatic scrolling.
4771+ *
4772+ * If automatic scrolling is disabled, one must explicitly call
4773+ * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
4774+ * current hash.
4775+ */
4776+ this.disableAutoScrolling = function() {
4777+ autoScrollingEnabled = false;
4778+ };
4779+
4780+ /**
4781+ * @ngdoc service
4782+ * @name $anchorScroll
4783+ * @kind function
4784+ * @requires $window
4785+ * @requires $location
4786+ * @requires $rootScope
4787+ *
4788+ * @description
4789+ * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
4790+ * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
4791+ * in the
4792+ * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#an-indicated-part-of-the-document).
4793+ *
4794+ * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
4795+ * match any anchor whenever it changes. This can be disabled by calling
4796+ * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
4797+ *
4798+ * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
4799+ * vertical scroll-offset (either fixed or dynamic).
4800+ *
4801+ * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of
4802+ * {@link ng.$location#hash $location.hash()} will be used.
4803+ *
4804+ * @property {(number|function|jqLite)} yOffset
4805+ * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
4806+ * positioned elements at the top of the page, such as navbars, headers etc.
4807+ *
4808+ * `yOffset` can be specified in various ways:
4809+ * - **number**: A fixed number of pixels to be used as offset.<br /><br />
4810+ * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
4811+ * a number representing the offset (in pixels).<br /><br />
4812+ * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
4813+ * the top of the page to the element's bottom will be used as offset.<br />
4814+ * **Note**: The element will be taken into account only as long as its `position` is set to
4815+ * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
4816+ * their height and/or positioning according to the viewport's size.
4817+ *
4818+ * <br />
4819+ * <div class="alert alert-warning">
4820+ * In order for `yOffset` to work properly, scrolling should take place on the document's root and
4821+ * not some child element.
4822+ * </div>
4823+ *
4824+ * @example
4825+ <example module="anchorScrollExample">
4826+ <file name="index.html">
4827+ <div id="scrollArea" ng-controller="ScrollController">
4828+ <a ng-click="gotoBottom()">Go to bottom</a>
4829+ <a id="bottom"></a> You're at the bottom!
4830+ </div>
4831+ </file>
4832+ <file name="script.js">
4833+ angular.module('anchorScrollExample', [])
4834+ .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
4835+ function ($scope, $location, $anchorScroll) {
4836+ $scope.gotoBottom = function() {
4837+ // set the location.hash to the id of
4838+ // the element you wish to scroll to.
4839+ $location.hash('bottom');
4840+
4841+ // call $anchorScroll()
4842+ $anchorScroll();
4843+ };
4844+ }]);
4845+ </file>
4846+ <file name="style.css">
4847+ #scrollArea {
4848+ height: 280px;
4849+ overflow: auto;
4850+ }
4851+
4852+ #bottom {
4853+ display: block;
4854+ margin-top: 2000px;
4855+ }
4856+ </file>
4857+ </example>
4858+ *
4859+ * <hr />
4860+ * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
4861+ * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
4862+ *
4863+ * @example
4864+ <example module="anchorScrollOffsetExample">
4865+ <file name="index.html">
4866+ <div class="fixed-header" ng-controller="headerCtrl">
4867+ <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
4868+ Go to anchor {{x}}
4869+ </a>
4870+ </div>
4871+ <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
4872+ Anchor {{x}} of 5
4873+ </div>
4874+ </file>
4875+ <file name="script.js">
4876+ angular.module('anchorScrollOffsetExample', [])
4877+ .run(['$anchorScroll', function($anchorScroll) {
4878+ $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
4879+ }])
4880+ .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
4881+ function ($anchorScroll, $location, $scope) {
4882+ $scope.gotoAnchor = function(x) {
4883+ var newHash = 'anchor' + x;
4884+ if ($location.hash() !== newHash) {
4885+ // set the $location.hash to `newHash` and
4886+ // $anchorScroll will automatically scroll to it
4887+ $location.hash('anchor' + x);
4888+ } else {
4889+ // call $anchorScroll() explicitly,
4890+ // since $location.hash hasn't changed
4891+ $anchorScroll();
4892+ }
4893+ };
4894+ }
4895+ ]);
4896+ </file>
4897+ <file name="style.css">
4898+ body {
4899+ padding-top: 50px;
4900+ }
4901+
4902+ .anchor {
4903+ border: 2px dashed DarkOrchid;
4904+ padding: 10px 10px 200px 10px;
4905+ }
4906+
4907+ .fixed-header {
4908+ background-color: rgba(0, 0, 0, 0.2);
4909+ height: 50px;
4910+ position: fixed;
4911+ top: 0; left: 0; right: 0;
4912+ }
4913+
4914+ .fixed-header > a {
4915+ display: inline-block;
4916+ margin: 5px 15px;
4917+ }
4918+ </file>
4919+ </example>
4920+ */
4921+ this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
4922+ var document = $window.document;
4923+
4924+ // Helper function to get first anchor from a NodeList
4925+ // (using `Array#some()` instead of `angular#forEach()` since it's more performant
4926+ // and working in all supported browsers.)
4927+ function getFirstAnchor(list) {
4928+ var result = null;
4929+ Array.prototype.some.call(list, function(element) {
4930+ if (nodeName_(element) === 'a') {
4931+ result = element;
4932+ return true;
4933+ }
4934+ });
4935+ return result;
4936+ }
4937+
4938+ function getYOffset() {
4939+
4940+ var offset = scroll.yOffset;
4941+
4942+ if (isFunction(offset)) {
4943+ offset = offset();
4944+ } else if (isElement(offset)) {
4945+ var elem = offset[0];
4946+ var style = $window.getComputedStyle(elem);
4947+ if (style.position !== 'fixed') {
4948+ offset = 0;
4949+ } else {
4950+ offset = elem.getBoundingClientRect().bottom;
4951+ }
4952+ } else if (!isNumber(offset)) {
4953+ offset = 0;
4954+ }
4955+
4956+ return offset;
4957+ }
4958+
4959+ function scrollTo(elem) {
4960+ if (elem) {
4961+ elem.scrollIntoView();
4962+
4963+ var offset = getYOffset();
4964+
4965+ if (offset) {
4966+ // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
4967+ // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
4968+ // top of the viewport.
4969+ //
4970+ // IF the number of pixels from the top of `elem` to the end of the page's content is less
4971+ // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
4972+ // way down the page.
4973+ //
4974+ // This is often the case for elements near the bottom of the page.
4975+ //
4976+ // In such cases we do not need to scroll the whole `offset` up, just the difference between
4977+ // the top of the element and the offset, which is enough to align the top of `elem` at the
4978+ // desired position.
4979+ var elemTop = elem.getBoundingClientRect().top;
4980+ $window.scrollBy(0, elemTop - offset);
4981+ }
4982+ } else {
4983+ $window.scrollTo(0, 0);
4984+ }
4985+ }
4986+
4987+ function scroll(hash) {
4988+ hash = isString(hash) ? hash : $location.hash();
4989+ var elm;
4990+
4991+ // empty hash, scroll to the top of the page
4992+ if (!hash) scrollTo(null);
4993+
4994+ // element with given id
4995+ else if ((elm = document.getElementById(hash))) scrollTo(elm);
4996+
4997+ // first anchor with given name :-D
4998+ else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
4999+

26769 more lines aren’t shown here.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t