Add an AngularJS test to DoYouEvenBench
[WebKit-https.git] / PerformanceTests / DoYouEvenBench / todomvc / architecture-examples / angularjs / bower_components / angular / angular.js
1 /**
2  * @license AngularJS v1.0.7
3  * (c) 2010-2012 Google, Inc. http://angularjs.org
4  * License: MIT
5  */
6 (function(window, document, undefined) {
7 'use strict';
8
9 ////////////////////////////////////
10
11 /**
12  * @ngdoc function
13  * @name angular.lowercase
14  * @function
15  *
16  * @description Converts the specified string to lowercase.
17  * @param {string} string String to be converted to lowercase.
18  * @returns {string} Lowercased string.
19  */
20 var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
21
22
23 /**
24  * @ngdoc function
25  * @name angular.uppercase
26  * @function
27  *
28  * @description Converts the specified string to uppercase.
29  * @param {string} string String to be converted to uppercase.
30  * @returns {string} Uppercased string.
31  */
32 var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
33
34
35 var manualLowercase = function(s) {
36   return isString(s)
37       ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
38       : s;
39 };
40 var manualUppercase = function(s) {
41   return isString(s)
42       ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
43       : s;
44 };
45
46
47 // String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
48 // locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
49 // with correct but slower alternatives.
50 if ('i' !== 'I'.toLowerCase()) {
51   lowercase = manualLowercase;
52   uppercase = manualUppercase;
53 }
54
55
56 var /** holds major version number for IE or NaN for real browsers */
57     msie              = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
58     jqLite,           // delay binding since jQuery could be loaded after us.
59     jQuery,           // delay binding
60     slice             = [].slice,
61     push              = [].push,
62     toString          = Object.prototype.toString,
63
64     /** @name angular */
65     angular           = window.angular || (window.angular = {}),
66     angularModule,
67     nodeName_,
68     uid               = ['0', '0', '0'];
69
70
71 /**
72  * @private
73  * @param {*} obj
74  * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
75  */
76 function isArrayLike(obj) {
77   if (!obj || (typeof obj.length !== 'number')) return false;
78
79   // We have on object which has length property. Should we treat it as array?
80   if (typeof obj.hasOwnProperty != 'function' &&
81       typeof obj.constructor != 'function') {
82     // This is here for IE8: it is a bogus object treat it as array;
83     return true;
84   } else  {
85     return obj instanceof JQLite ||                      // JQLite
86            (jQuery && obj instanceof jQuery) ||          // jQuery
87            toString.call(obj) !== '[object Object]' ||   // some browser native object
88            typeof obj.callee === 'function';              // arguments (on IE8 looks like regular obj)
89   }
90 }
91
92
93 /**
94  * @ngdoc function
95  * @name angular.forEach
96  * @function
97  *
98  * @description
99  * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
100  * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
101  * is the value of an object property or an array element and `key` is the object property key or
102  * array element index. Specifying a `context` for the function is optional.
103  *
104  * Note: this function was previously known as `angular.foreach`.
105  *
106    <pre>
107      var values = {name: 'misko', gender: 'male'};
108      var log = [];
109      angular.forEach(values, function(value, key){
110        this.push(key + ': ' + value);
111      }, log);
112      expect(log).toEqual(['name: misko', 'gender:male']);
113    </pre>
114  *
115  * @param {Object|Array} obj Object to iterate over.
116  * @param {Function} iterator Iterator function.
117  * @param {Object=} context Object to become context (`this`) for the iterator function.
118  * @returns {Object|Array} Reference to `obj`.
119  */
120 function forEach(obj, iterator, context) {
121   var key;
122   if (obj) {
123     if (isFunction(obj)){
124       for (key in obj) {
125         if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
126           iterator.call(context, obj[key], key);
127         }
128       }
129     } else if (obj.forEach && obj.forEach !== forEach) {
130       obj.forEach(iterator, context);
131     } else if (isArrayLike(obj)) {
132       for (key = 0; key < obj.length; key++)
133         iterator.call(context, obj[key], key);
134     } else {
135       for (key in obj) {
136         if (obj.hasOwnProperty(key)) {
137           iterator.call(context, obj[key], key);
138         }
139       }
140     }
141   }
142   return obj;
143 }
144
145 function sortedKeys(obj) {
146   var keys = [];
147   for (var key in obj) {
148     if (obj.hasOwnProperty(key)) {
149       keys.push(key);
150     }
151   }
152   return keys.sort();
153 }
154
155 function forEachSorted(obj, iterator, context) {
156   var keys = sortedKeys(obj);
157   for ( var i = 0; i < keys.length; i++) {
158     iterator.call(context, obj[keys[i]], keys[i]);
159   }
160   return keys;
161 }
162
163
164 /**
165  * when using forEach the params are value, key, but it is often useful to have key, value.
166  * @param {function(string, *)} iteratorFn
167  * @returns {function(*, string)}
168  */
169 function reverseParams(iteratorFn) {
170   return function(value, key) { iteratorFn(key, value) };
171 }
172
173 /**
174  * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
175  * characters such as '012ABC'. The reason why we are not using simply a number counter is that
176  * the number string gets longer over time, and it can also overflow, where as the nextId
177  * will grow much slower, it is a string, and it will never overflow.
178  *
179  * @returns an unique alpha-numeric string
180  */
181 function nextUid() {
182   var index = uid.length;
183   var digit;
184
185   while(index) {
186     index--;
187     digit = uid[index].charCodeAt(0);
188     if (digit == 57 /*'9'*/) {
189       uid[index] = 'A';
190       return uid.join('');
191     }
192     if (digit == 90  /*'Z'*/) {
193       uid[index] = '0';
194     } else {
195       uid[index] = String.fromCharCode(digit + 1);
196       return uid.join('');
197     }
198   }
199   uid.unshift('0');
200   return uid.join('');
201 }
202
203
204 /**
205  * Set or clear the hashkey for an object.
206  * @param obj object 
207  * @param h the hashkey (!truthy to delete the hashkey)
208  */
209 function setHashKey(obj, h) {
210   if (h) {
211     obj.$$hashKey = h;
212   }
213   else {
214     delete obj.$$hashKey;
215   }
216 }
217
218 /**
219  * @ngdoc function
220  * @name angular.extend
221  * @function
222  *
223  * @description
224  * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
225  * to `dst`. You can specify multiple `src` objects.
226  *
227  * @param {Object} dst Destination object.
228  * @param {...Object} src Source object(s).
229  * @returns {Object} Reference to `dst`.
230  */
231 function extend(dst) {
232   var h = dst.$$hashKey;
233   forEach(arguments, function(obj){
234     if (obj !== dst) {
235       forEach(obj, function(value, key){
236         dst[key] = value;
237       });
238     }
239   });
240
241   setHashKey(dst,h);
242   return dst;
243 }
244
245 function int(str) {
246   return parseInt(str, 10);
247 }
248
249
250 function inherit(parent, extra) {
251   return extend(new (extend(function() {}, {prototype:parent}))(), extra);
252 }
253
254
255 /**
256  * @ngdoc function
257  * @name angular.noop
258  * @function
259  *
260  * @description
261  * A function that performs no operations. This function can be useful when writing code in the
262  * functional style.
263    <pre>
264      function foo(callback) {
265        var result = calculateResult();
266        (callback || angular.noop)(result);
267      }
268    </pre>
269  */
270 function noop() {}
271 noop.$inject = [];
272
273
274 /**
275  * @ngdoc function
276  * @name angular.identity
277  * @function
278  *
279  * @description
280  * A function that returns its first argument. This function is useful when writing code in the
281  * functional style.
282  *
283    <pre>
284      function transformer(transformationFn, value) {
285        return (transformationFn || identity)(value);
286      };
287    </pre>
288  */
289 function identity($) {return $;}
290 identity.$inject = [];
291
292
293 function valueFn(value) {return function() {return value;};}
294
295 /**
296  * @ngdoc function
297  * @name angular.isUndefined
298  * @function
299  *
300  * @description
301  * Determines if a reference is undefined.
302  *
303  * @param {*} value Reference to check.
304  * @returns {boolean} True if `value` is undefined.
305  */
306 function isUndefined(value){return typeof value == 'undefined';}
307
308
309 /**
310  * @ngdoc function
311  * @name angular.isDefined
312  * @function
313  *
314  * @description
315  * Determines if a reference is defined.
316  *
317  * @param {*} value Reference to check.
318  * @returns {boolean} True if `value` is defined.
319  */
320 function isDefined(value){return typeof value != 'undefined';}
321
322
323 /**
324  * @ngdoc function
325  * @name angular.isObject
326  * @function
327  *
328  * @description
329  * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
330  * considered to be objects.
331  *
332  * @param {*} value Reference to check.
333  * @returns {boolean} True if `value` is an `Object` but not `null`.
334  */
335 function isObject(value){return value != null && typeof value == 'object';}
336
337
338 /**
339  * @ngdoc function
340  * @name angular.isString
341  * @function
342  *
343  * @description
344  * Determines if a reference is a `String`.
345  *
346  * @param {*} value Reference to check.
347  * @returns {boolean} True if `value` is a `String`.
348  */
349 function isString(value){return typeof value == 'string';}
350
351
352 /**
353  * @ngdoc function
354  * @name angular.isNumber
355  * @function
356  *
357  * @description
358  * Determines if a reference is a `Number`.
359  *
360  * @param {*} value Reference to check.
361  * @returns {boolean} True if `value` is a `Number`.
362  */
363 function isNumber(value){return typeof value == 'number';}
364
365
366 /**
367  * @ngdoc function
368  * @name angular.isDate
369  * @function
370  *
371  * @description
372  * Determines if a value is a date.
373  *
374  * @param {*} value Reference to check.
375  * @returns {boolean} True if `value` is a `Date`.
376  */
377 function isDate(value){
378   return toString.apply(value) == '[object Date]';
379 }
380
381
382 /**
383  * @ngdoc function
384  * @name angular.isArray
385  * @function
386  *
387  * @description
388  * Determines if a reference is an `Array`.
389  *
390  * @param {*} value Reference to check.
391  * @returns {boolean} True if `value` is an `Array`.
392  */
393 function isArray(value) {
394   return toString.apply(value) == '[object Array]';
395 }
396
397
398 /**
399  * @ngdoc function
400  * @name angular.isFunction
401  * @function
402  *
403  * @description
404  * Determines if a reference is a `Function`.
405  *
406  * @param {*} value Reference to check.
407  * @returns {boolean} True if `value` is a `Function`.
408  */
409 function isFunction(value){return typeof value == 'function';}
410
411
412 /**
413  * Checks if `obj` is a window object.
414  *
415  * @private
416  * @param {*} obj Object to check
417  * @returns {boolean} True if `obj` is a window obj.
418  */
419 function isWindow(obj) {
420   return obj && obj.document && obj.location && obj.alert && obj.setInterval;
421 }
422
423
424 function isScope(obj) {
425   return obj && obj.$evalAsync && obj.$watch;
426 }
427
428
429 function isFile(obj) {
430   return toString.apply(obj) === '[object File]';
431 }
432
433
434 function isBoolean(value) {
435   return typeof value == 'boolean';
436 }
437
438
439 function trim(value) {
440   return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value;
441 }
442
443 /**
444  * @ngdoc function
445  * @name angular.isElement
446  * @function
447  *
448  * @description
449  * Determines if a reference is a DOM element (or wrapped jQuery element).
450  *
451  * @param {*} value Reference to check.
452  * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
453  */
454 function isElement(node) {
455   return node &&
456     (node.nodeName  // we are a direct element
457     || (node.bind && node.find));  // we have a bind and find method part of jQuery API
458 }
459
460 /**
461  * @param str 'key1,key2,...'
462  * @returns {object} in the form of {key1:true, key2:true, ...}
463  */
464 function makeMap(str){
465   var obj = {}, items = str.split(","), i;
466   for ( i = 0; i < items.length; i++ )
467     obj[ items[i] ] = true;
468   return obj;
469 }
470
471
472 if (msie < 9) {
473   nodeName_ = function(element) {
474     element = element.nodeName ? element : element[0];
475     return (element.scopeName && element.scopeName != 'HTML')
476       ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
477   };
478 } else {
479   nodeName_ = function(element) {
480     return element.nodeName ? element.nodeName : element[0].nodeName;
481   };
482 }
483
484
485 function map(obj, iterator, context) {
486   var results = [];
487   forEach(obj, function(value, index, list) {
488     results.push(iterator.call(context, value, index, list));
489   });
490   return results;
491 }
492
493
494 /**
495  * @description
496  * Determines the number of elements in an array, the number of properties an object has, or
497  * the length of a string.
498  *
499  * Note: This function is used to augment the Object type in Angular expressions. See
500  * {@link angular.Object} for more information about Angular arrays.
501  *
502  * @param {Object|Array|string} obj Object, array, or string to inspect.
503  * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
504  * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
505  */
506 function size(obj, ownPropsOnly) {
507   var size = 0, key;
508
509   if (isArray(obj) || isString(obj)) {
510     return obj.length;
511   } else if (isObject(obj)){
512     for (key in obj)
513       if (!ownPropsOnly || obj.hasOwnProperty(key))
514         size++;
515   }
516
517   return size;
518 }
519
520
521 function includes(array, obj) {
522   return indexOf(array, obj) != -1;
523 }
524
525 function indexOf(array, obj) {
526   if (array.indexOf) return array.indexOf(obj);
527
528   for ( var i = 0; i < array.length; i++) {
529     if (obj === array[i]) return i;
530   }
531   return -1;
532 }
533
534 function arrayRemove(array, value) {
535   var index = indexOf(array, value);
536   if (index >=0)
537     array.splice(index, 1);
538   return value;
539 }
540
541 function isLeafNode (node) {
542   if (node) {
543     switch (node.nodeName) {
544     case "OPTION":
545     case "PRE":
546     case "TITLE":
547       return true;
548     }
549   }
550   return false;
551 }
552
553 /**
554  * @ngdoc function
555  * @name angular.copy
556  * @function
557  *
558  * @description
559  * Creates a deep copy of `source`, which should be an object or an array.
560  *
561  * * If no destination is supplied, a copy of the object or array is created.
562  * * If a destination is provided, all of its elements (for array) or properties (for objects)
563  *   are deleted and then all elements/properties from the source are copied to it.
564  * * If  `source` is not an object or array, `source` is returned.
565  *
566  * Note: this function is used to augment the Object type in Angular expressions. See
567  * {@link ng.$filter} for more information about Angular arrays.
568  *
569  * @param {*} source The source that will be used to make a copy.
570  *                   Can be any type, including primitives, `null`, and `undefined`.
571  * @param {(Object|Array)=} destination Destination into which the source is copied. If
572  *     provided, must be of the same type as `source`.
573  * @returns {*} The copy or updated `destination`, if `destination` was specified.
574  */
575 function copy(source, destination){
576   if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope");
577   if (!destination) {
578     destination = source;
579     if (source) {
580       if (isArray(source)) {
581         destination = copy(source, []);
582       } else if (isDate(source)) {
583         destination = new Date(source.getTime());
584       } else if (isObject(source)) {
585         destination = copy(source, {});
586       }
587     }
588   } else {
589     if (source === destination) throw Error("Can't copy equivalent objects or arrays");
590     if (isArray(source)) {
591       destination.length = 0;
592       for ( var i = 0; i < source.length; i++) {
593         destination.push(copy(source[i]));
594       }
595     } else {
596       var h = destination.$$hashKey;
597       forEach(destination, function(value, key){
598         delete destination[key];
599       });
600       for ( var key in source) {
601         destination[key] = copy(source[key]);
602       }
603       setHashKey(destination,h);
604     }
605   }
606   return destination;
607 }
608
609 /**
610  * Create a shallow copy of an object
611  */
612 function shallowCopy(src, dst) {
613   dst = dst || {};
614
615   for(var key in src) {
616     if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
617       dst[key] = src[key];
618     }
619   }
620
621   return dst;
622 }
623
624
625 /**
626  * @ngdoc function
627  * @name angular.equals
628  * @function
629  *
630  * @description
631  * Determines if two objects or two values are equivalent. Supports value types, arrays and
632  * objects.
633  *
634  * Two objects or values are considered equivalent if at least one of the following is true:
635  *
636  * * Both objects or values pass `===` comparison.
637  * * Both objects or values are of the same type and all of their properties pass `===` comparison.
638  * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)
639  *
640  * During a property comparision, properties of `function` type and properties with names
641  * that begin with `$` are ignored.
642  *
643  * Scope and DOMWindow objects are being compared only by identify (`===`).
644  *
645  * @param {*} o1 Object or value to compare.
646  * @param {*} o2 Object or value to compare.
647  * @returns {boolean} True if arguments are equal.
648  */
649 function equals(o1, o2) {
650   if (o1 === o2) return true;
651   if (o1 === null || o2 === null) return false;
652   if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
653   var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
654   if (t1 == t2) {
655     if (t1 == 'object') {
656       if (isArray(o1)) {
657         if ((length = o1.length) == o2.length) {
658           for(key=0; key<length; key++) {
659             if (!equals(o1[key], o2[key])) return false;
660           }
661           return true;
662         }
663       } else if (isDate(o1)) {
664         return isDate(o2) && o1.getTime() == o2.getTime();
665       } else {
666         if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
667         keySet = {};
668         for(key in o1) {
669           if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
670           if (!equals(o1[key], o2[key])) return false;
671           keySet[key] = true;
672         }
673         for(key in o2) {
674           if (!keySet[key] &&
675               key.charAt(0) !== '$' &&
676               o2[key] !== undefined &&
677               !isFunction(o2[key])) return false;
678         }
679         return true;
680       }
681     }
682   }
683   return false;
684 }
685
686
687 function concat(array1, array2, index) {
688   return array1.concat(slice.call(array2, index));
689 }
690
691 function sliceArgs(args, startIndex) {
692   return slice.call(args, startIndex || 0);
693 }
694
695
696 /**
697  * @ngdoc function
698  * @name angular.bind
699  * @function
700  *
701  * @description
702  * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
703  * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
704  * known as [function currying](http://en.wikipedia.org/wiki/Currying).
705  *
706  * @param {Object} self Context which `fn` should be evaluated in.
707  * @param {function()} fn Function to be bound.
708  * @param {...*} args Optional arguments to be prebound to the `fn` function call.
709  * @returns {function()} Function that wraps the `fn` with all the specified bindings.
710  */
711 function bind(self, fn) {
712   var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
713   if (isFunction(fn) && !(fn instanceof RegExp)) {
714     return curryArgs.length
715       ? function() {
716           return arguments.length
717             ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
718             : fn.apply(self, curryArgs);
719         }
720       : function() {
721           return arguments.length
722             ? fn.apply(self, arguments)
723             : fn.call(self);
724         };
725   } else {
726     // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
727     return fn;
728   }
729 }
730
731
732 function toJsonReplacer(key, value) {
733   var val = value;
734
735   if (/^\$+/.test(key)) {
736     val = undefined;
737   } else if (isWindow(value)) {
738     val = '$WINDOW';
739   } else if (value &&  document === value) {
740     val = '$DOCUMENT';
741   } else if (isScope(value)) {
742     val = '$SCOPE';
743   }
744
745   return val;
746 }
747
748
749 /**
750  * @ngdoc function
751  * @name angular.toJson
752  * @function
753  *
754  * @description
755  * Serializes input into a JSON-formatted string.
756  *
757  * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
758  * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
759  * @returns {string} Jsonified string representing `obj`.
760  */
761 function toJson(obj, pretty) {
762   return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
763 }
764
765
766 /**
767  * @ngdoc function
768  * @name angular.fromJson
769  * @function
770  *
771  * @description
772  * Deserializes a JSON string.
773  *
774  * @param {string} json JSON string to deserialize.
775  * @returns {Object|Array|Date|string|number} Deserialized thingy.
776  */
777 function fromJson(json) {
778   return isString(json)
779       ? JSON.parse(json)
780       : json;
781 }
782
783
784 function toBoolean(value) {
785   if (value && value.length !== 0) {
786     var v = lowercase("" + value);
787     value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
788   } else {
789     value = false;
790   }
791   return value;
792 }
793
794 /**
795  * @returns {string} Returns the string representation of the element.
796  */
797 function startingTag(element) {
798   element = jqLite(element).clone();
799   try {
800     // turns out IE does not let you set .html() on elements which
801     // are not allowed to have children. So we just ignore it.
802     element.html('');
803   } catch(e) {}
804   // As Per DOM Standards
805   var TEXT_NODE = 3;
806   var elemHtml = jqLite('<div>').append(element).html();
807   try {
808     return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
809         elemHtml.
810           match(/^(<[^>]+>)/)[1].
811           replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
812   } catch(e) {
813     return lowercase(elemHtml);
814   }
815
816 }
817
818
819 /////////////////////////////////////////////////
820
821 /**
822  * Parses an escaped url query string into key-value pairs.
823  * @returns Object.<(string|boolean)>
824  */
825 function parseKeyValue(/**string*/keyValue) {
826   var obj = {}, key_value, key;
827   forEach((keyValue || "").split('&'), function(keyValue){
828     if (keyValue) {
829       key_value = keyValue.split('=');
830       key = decodeURIComponent(key_value[0]);
831       obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;
832     }
833   });
834   return obj;
835 }
836
837 function toKeyValue(obj) {
838   var parts = [];
839   forEach(obj, function(value, key) {
840     parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));
841   });
842   return parts.length ? parts.join('&') : '';
843 }
844
845
846 /**
847  * We need our custom method because encodeURIComponent is too agressive and doesn't follow
848  * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
849  * segments:
850  *    segment       = *pchar
851  *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
852  *    pct-encoded   = "%" HEXDIG HEXDIG
853  *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
854  *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
855  *                     / "*" / "+" / "," / ";" / "="
856  */
857 function encodeUriSegment(val) {
858   return encodeUriQuery(val, true).
859              replace(/%26/gi, '&').
860              replace(/%3D/gi, '=').
861              replace(/%2B/gi, '+');
862 }
863
864
865 /**
866  * This method is intended for encoding *key* or *value* parts of query component. We need a custom
867  * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
868  * encoded per http://tools.ietf.org/html/rfc3986:
869  *    query       = *( pchar / "/" / "?" )
870  *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
871  *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
872  *    pct-encoded   = "%" HEXDIG HEXDIG
873  *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
874  *                     / "*" / "+" / "," / ";" / "="
875  */
876 function encodeUriQuery(val, pctEncodeSpaces) {
877   return encodeURIComponent(val).
878              replace(/%40/gi, '@').
879              replace(/%3A/gi, ':').
880              replace(/%24/g, '$').
881              replace(/%2C/gi, ',').
882              replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
883 }
884
885
886 /**
887  * @ngdoc directive
888  * @name ng.directive:ngApp
889  *
890  * @element ANY
891  * @param {angular.Module} ngApp an optional application
892  *   {@link angular.module module} name to load.
893  *
894  * @description
895  *
896  * Use this directive to auto-bootstrap an application. Only
897  * one directive can be used per HTML document. The directive
898  * designates the root of the application and is typically placed
899  * at the root of the page.
900  *
901  * In the example below if the `ngApp` directive would not be placed
902  * on the `html` element then the document would not be compiled
903  * and the `{{ 1+2 }}` would not be resolved to `3`.
904  *
905  * `ngApp` is the easiest way to bootstrap an application.
906  *
907  <doc:example>
908    <doc:source>
909     I can add: 1 + 2 =  {{ 1+2 }}
910    </doc:source>
911  </doc:example>
912  *
913  */
914 function angularInit(element, bootstrap) {
915   var elements = [element],
916       appElement,
917       module,
918       names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
919       NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
920
921   function append(element) {
922     element && elements.push(element);
923   }
924
925   forEach(names, function(name) {
926     names[name] = true;
927     append(document.getElementById(name));
928     name = name.replace(':', '\\:');
929     if (element.querySelectorAll) {
930       forEach(element.querySelectorAll('.' + name), append);
931       forEach(element.querySelectorAll('.' + name + '\\:'), append);
932       forEach(element.querySelectorAll('[' + name + ']'), append);
933     }
934   });
935
936   forEach(elements, function(element) {
937     if (!appElement) {
938       var className = ' ' + element.className + ' ';
939       var match = NG_APP_CLASS_REGEXP.exec(className);
940       if (match) {
941         appElement = element;
942         module = (match[2] || '').replace(/\s+/g, ',');
943       } else {
944         forEach(element.attributes, function(attr) {
945           if (!appElement && names[attr.name]) {
946             appElement = element;
947             module = attr.value;
948           }
949         });
950       }
951     }
952   });
953   if (appElement) {
954     bootstrap(appElement, module ? [module] : []);
955   }
956 }
957
958 /**
959  * @ngdoc function
960  * @name angular.bootstrap
961  * @description
962  * Use this function to manually start up angular application.
963  *
964  * See: {@link guide/bootstrap Bootstrap}
965  *
966  * @param {Element} element DOM element which is the root of angular application.
967  * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}
968  * @returns {AUTO.$injector} Returns the newly created injector for this app.
969  */
970 function bootstrap(element, modules) {
971   var resumeBootstrapInternal = function() {
972     element = jqLite(element);
973     modules = modules || [];
974     modules.unshift(['$provide', function($provide) {
975       $provide.value('$rootElement', element);
976     }]);
977     modules.unshift('ng');
978     var injector = createInjector(modules);
979     injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
980        function(scope, element, compile, injector) {
981         scope.$apply(function() {
982           element.data('$injector', injector);
983           compile(element)(scope);
984         });
985       }]
986     );
987     return injector;
988   };
989
990   var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
991
992   if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
993     return resumeBootstrapInternal();
994   }
995
996   window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
997   angular.resumeBootstrap = function(extraModules) {
998     forEach(extraModules, function(module) {
999       modules.push(module);
1000     });
1001     resumeBootstrapInternal();
1002   };
1003 }
1004
1005 var SNAKE_CASE_REGEXP = /[A-Z]/g;
1006 function snake_case(name, separator){
1007   separator = separator || '_';
1008   return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
1009     return (pos ? separator : '') + letter.toLowerCase();
1010   });
1011 }
1012
1013 function bindJQuery() {
1014   // bind to jQuery if present;
1015   jQuery = window.jQuery;
1016   // reset to jQuery or default to us.
1017   if (jQuery) {
1018     jqLite = jQuery;
1019     extend(jQuery.fn, {
1020       scope: JQLitePrototype.scope,
1021       controller: JQLitePrototype.controller,
1022       injector: JQLitePrototype.injector,
1023       inheritedData: JQLitePrototype.inheritedData
1024     });
1025     JQLitePatchJQueryRemove('remove', true);
1026     JQLitePatchJQueryRemove('empty');
1027     JQLitePatchJQueryRemove('html');
1028   } else {
1029     jqLite = JQLite;
1030   }
1031   angular.element = jqLite;
1032 }
1033
1034 /**
1035  * throw error if the argument is falsy.
1036  */
1037 function assertArg(arg, name, reason) {
1038   if (!arg) {
1039     throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required"));
1040   }
1041   return arg;
1042 }
1043
1044 function assertArgFn(arg, name, acceptArrayAnnotation) {
1045   if (acceptArrayAnnotation && isArray(arg)) {
1046       arg = arg[arg.length - 1];
1047   }
1048
1049   assertArg(isFunction(arg), name, 'not a function, got ' +
1050       (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
1051   return arg;
1052 }
1053
1054 /**
1055  * @ngdoc interface
1056  * @name angular.Module
1057  * @description
1058  *
1059  * Interface for configuring angular {@link angular.module modules}.
1060  */
1061
1062 function setupModuleLoader(window) {
1063
1064   function ensure(obj, name, factory) {
1065     return obj[name] || (obj[name] = factory());
1066   }
1067
1068   return ensure(ensure(window, 'angular', Object), 'module', function() {
1069     /** @type {Object.<string, angular.Module>} */
1070     var modules = {};
1071
1072     /**
1073      * @ngdoc function
1074      * @name angular.module
1075      * @description
1076      *
1077      * The `angular.module` is a global place for creating and registering Angular modules. All
1078      * modules (angular core or 3rd party) that should be available to an application must be
1079      * registered using this mechanism.
1080      *
1081      *
1082      * # Module
1083      *
1084      * A module is a collocation of services, directives, filters, and configuration information. Module
1085      * is used to configure the {@link AUTO.$injector $injector}.
1086      *
1087      * <pre>
1088      * // Create a new module
1089      * var myModule = angular.module('myModule', []);
1090      *
1091      * // register a new service
1092      * myModule.value('appName', 'MyCoolApp');
1093      *
1094      * // configure existing services inside initialization blocks.
1095      * myModule.config(function($locationProvider) {
1096      *   // Configure existing providers
1097      *   $locationProvider.hashPrefix('!');
1098      * });
1099      * </pre>
1100      *
1101      * Then you can create an injector and load your modules like this:
1102      *
1103      * <pre>
1104      * var injector = angular.injector(['ng', 'MyModule'])
1105      * </pre>
1106      *
1107      * However it's more likely that you'll just use
1108      * {@link ng.directive:ngApp ngApp} or
1109      * {@link angular.bootstrap} to simplify this process for you.
1110      *
1111      * @param {!string} name The name of the module to create or retrieve.
1112      * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
1113      *        the module is being retrieved for further configuration.
1114      * @param {Function} configFn Optional configuration function for the module. Same as
1115      *        {@link angular.Module#config Module#config()}.
1116      * @returns {module} new module with the {@link angular.Module} api.
1117      */
1118     return function module(name, requires, configFn) {
1119       if (requires && modules.hasOwnProperty(name)) {
1120         modules[name] = null;
1121       }
1122       return ensure(modules, name, function() {
1123         if (!requires) {
1124           throw Error('No module: ' + name);
1125         }
1126
1127         /** @type {!Array.<Array.<*>>} */
1128         var invokeQueue = [];
1129
1130         /** @type {!Array.<Function>} */
1131         var runBlocks = [];
1132
1133         var config = invokeLater('$injector', 'invoke');
1134
1135         /** @type {angular.Module} */
1136         var moduleInstance = {
1137           // Private state
1138           _invokeQueue: invokeQueue,
1139           _runBlocks: runBlocks,
1140
1141           /**
1142            * @ngdoc property
1143            * @name angular.Module#requires
1144            * @propertyOf angular.Module
1145            * @returns {Array.<string>} List of module names which must be loaded before this module.
1146            * @description
1147            * Holds the list of modules which the injector will load before the current module is loaded.
1148            */
1149           requires: requires,
1150
1151           /**
1152            * @ngdoc property
1153            * @name angular.Module#name
1154            * @propertyOf angular.Module
1155            * @returns {string} Name of the module.
1156            * @description
1157            */
1158           name: name,
1159
1160
1161           /**
1162            * @ngdoc method
1163            * @name angular.Module#provider
1164            * @methodOf angular.Module
1165            * @param {string} name service name
1166            * @param {Function} providerType Construction function for creating new instance of the service.
1167            * @description
1168            * See {@link AUTO.$provide#provider $provide.provider()}.
1169            */
1170           provider: invokeLater('$provide', 'provider'),
1171
1172           /**
1173            * @ngdoc method
1174            * @name angular.Module#factory
1175            * @methodOf angular.Module
1176            * @param {string} name service name
1177            * @param {Function} providerFunction Function for creating new instance of the service.
1178            * @description
1179            * See {@link AUTO.$provide#factory $provide.factory()}.
1180            */
1181           factory: invokeLater('$provide', 'factory'),
1182
1183           /**
1184            * @ngdoc method
1185            * @name angular.Module#service
1186            * @methodOf angular.Module
1187            * @param {string} name service name
1188            * @param {Function} constructor A constructor function that will be instantiated.
1189            * @description
1190            * See {@link AUTO.$provide#service $provide.service()}.
1191            */
1192           service: invokeLater('$provide', 'service'),
1193
1194           /**
1195            * @ngdoc method
1196            * @name angular.Module#value
1197            * @methodOf angular.Module
1198            * @param {string} name service name
1199            * @param {*} object Service instance object.
1200            * @description
1201            * See {@link AUTO.$provide#value $provide.value()}.
1202            */
1203           value: invokeLater('$provide', 'value'),
1204
1205           /**
1206            * @ngdoc method
1207            * @name angular.Module#constant
1208            * @methodOf angular.Module
1209            * @param {string} name constant name
1210            * @param {*} object Constant value.
1211            * @description
1212            * Because the constant are fixed, they get applied before other provide methods.
1213            * See {@link AUTO.$provide#constant $provide.constant()}.
1214            */
1215           constant: invokeLater('$provide', 'constant', 'unshift'),
1216
1217           /**
1218            * @ngdoc method
1219            * @name angular.Module#filter
1220            * @methodOf angular.Module
1221            * @param {string} name Filter name.
1222            * @param {Function} filterFactory Factory function for creating new instance of filter.
1223            * @description
1224            * See {@link ng.$filterProvider#register $filterProvider.register()}.
1225            */
1226           filter: invokeLater('$filterProvider', 'register'),
1227
1228           /**
1229            * @ngdoc method
1230            * @name angular.Module#controller
1231            * @methodOf angular.Module
1232            * @param {string} name Controller name.
1233            * @param {Function} constructor Controller constructor function.
1234            * @description
1235            * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
1236            */
1237           controller: invokeLater('$controllerProvider', 'register'),
1238
1239           /**
1240            * @ngdoc method
1241            * @name angular.Module#directive
1242            * @methodOf angular.Module
1243            * @param {string} name directive name
1244            * @param {Function} directiveFactory Factory function for creating new instance of
1245            * directives.
1246            * @description
1247            * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
1248            */
1249           directive: invokeLater('$compileProvider', 'directive'),
1250
1251           /**
1252            * @ngdoc method
1253            * @name angular.Module#config
1254            * @methodOf angular.Module
1255            * @param {Function} configFn Execute this function on module load. Useful for service
1256            *    configuration.
1257            * @description
1258            * Use this method to register work which needs to be performed on module loading.
1259            */
1260           config: config,
1261
1262           /**
1263            * @ngdoc method
1264            * @name angular.Module#run
1265            * @methodOf angular.Module
1266            * @param {Function} initializationFn Execute this function after injector creation.
1267            *    Useful for application initialization.
1268            * @description
1269            * Use this method to register work which should be performed when the injector is done
1270            * loading all modules.
1271            */
1272           run: function(block) {
1273             runBlocks.push(block);
1274             return this;
1275           }
1276         };
1277
1278         if (configFn) {
1279           config(configFn);
1280         }
1281
1282         return  moduleInstance;
1283
1284         /**
1285          * @param {string} provider
1286          * @param {string} method
1287          * @param {String=} insertMethod
1288          * @returns {angular.Module}
1289          */
1290         function invokeLater(provider, method, insertMethod) {
1291           return function() {
1292             invokeQueue[insertMethod || 'push']([provider, method, arguments]);
1293             return moduleInstance;
1294           }
1295         }
1296       });
1297     };
1298   });
1299
1300 }
1301
1302 /**
1303  * @ngdoc property
1304  * @name angular.version
1305  * @description
1306  * An object that contains information about the current AngularJS version. This object has the
1307  * following properties:
1308  *
1309  * - `full` – `{string}` – Full version string, such as "0.9.18".
1310  * - `major` – `{number}` – Major version number, such as "0".
1311  * - `minor` – `{number}` – Minor version number, such as "9".
1312  * - `dot` – `{number}` – Dot version number, such as "18".
1313  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
1314  */
1315 var version = {
1316   full: '1.0.7',    // all of these placeholder strings will be replaced by grunt's
1317   major: 1,    // package task
1318   minor: 0,
1319   dot: 7,
1320   codeName: 'monochromatic-rainbow'
1321 };
1322
1323
1324 function publishExternalAPI(angular){
1325   extend(angular, {
1326     'bootstrap': bootstrap,
1327     'copy': copy,
1328     'extend': extend,
1329     'equals': equals,
1330     'element': jqLite,
1331     'forEach': forEach,
1332     'injector': createInjector,
1333     'noop':noop,
1334     'bind':bind,
1335     'toJson': toJson,
1336     'fromJson': fromJson,
1337     'identity':identity,
1338     'isUndefined': isUndefined,
1339     'isDefined': isDefined,
1340     'isString': isString,
1341     'isFunction': isFunction,
1342     'isObject': isObject,
1343     'isNumber': isNumber,
1344     'isElement': isElement,
1345     'isArray': isArray,
1346     'version': version,
1347     'isDate': isDate,
1348     'lowercase': lowercase,
1349     'uppercase': uppercase,
1350     'callbacks': {counter: 0}
1351   });
1352
1353   angularModule = setupModuleLoader(window);
1354   try {
1355     angularModule('ngLocale');
1356   } catch (e) {
1357     angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
1358   }
1359
1360   angularModule('ng', ['ngLocale'], ['$provide',
1361     function ngModule($provide) {
1362       $provide.provider('$compile', $CompileProvider).
1363         directive({
1364             a: htmlAnchorDirective,
1365             input: inputDirective,
1366             textarea: inputDirective,
1367             form: formDirective,
1368             script: scriptDirective,
1369             select: selectDirective,
1370             style: styleDirective,
1371             option: optionDirective,
1372             ngBind: ngBindDirective,
1373             ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,
1374             ngBindTemplate: ngBindTemplateDirective,
1375             ngClass: ngClassDirective,
1376             ngClassEven: ngClassEvenDirective,
1377             ngClassOdd: ngClassOddDirective,
1378             ngCsp: ngCspDirective,
1379             ngCloak: ngCloakDirective,
1380             ngController: ngControllerDirective,
1381             ngForm: ngFormDirective,
1382             ngHide: ngHideDirective,
1383             ngInclude: ngIncludeDirective,
1384             ngInit: ngInitDirective,
1385             ngNonBindable: ngNonBindableDirective,
1386             ngPluralize: ngPluralizeDirective,
1387             ngRepeat: ngRepeatDirective,
1388             ngShow: ngShowDirective,
1389             ngSubmit: ngSubmitDirective,
1390             ngStyle: ngStyleDirective,
1391             ngSwitch: ngSwitchDirective,
1392             ngSwitchWhen: ngSwitchWhenDirective,
1393             ngSwitchDefault: ngSwitchDefaultDirective,
1394             ngOptions: ngOptionsDirective,
1395             ngView: ngViewDirective,
1396             ngTransclude: ngTranscludeDirective,
1397             ngModel: ngModelDirective,
1398             ngList: ngListDirective,
1399             ngChange: ngChangeDirective,
1400             required: requiredDirective,
1401             ngRequired: requiredDirective,
1402             ngValue: ngValueDirective
1403         }).
1404         directive(ngAttributeAliasDirectives).
1405         directive(ngEventDirectives);
1406       $provide.provider({
1407         $anchorScroll: $AnchorScrollProvider,
1408         $browser: $BrowserProvider,
1409         $cacheFactory: $CacheFactoryProvider,
1410         $controller: $ControllerProvider,
1411         $document: $DocumentProvider,
1412         $exceptionHandler: $ExceptionHandlerProvider,
1413         $filter: $FilterProvider,
1414         $interpolate: $InterpolateProvider,
1415         $http: $HttpProvider,
1416         $httpBackend: $HttpBackendProvider,
1417         $location: $LocationProvider,
1418         $log: $LogProvider,
1419         $parse: $ParseProvider,
1420         $route: $RouteProvider,
1421         $routeParams: $RouteParamsProvider,
1422         $rootScope: $RootScopeProvider,
1423         $q: $QProvider,
1424         $sniffer: $SnifferProvider,
1425         $templateCache: $TemplateCacheProvider,
1426         $timeout: $TimeoutProvider,
1427         $window: $WindowProvider
1428       });
1429     }
1430   ]);
1431 }
1432
1433 //////////////////////////////////
1434 //JQLite
1435 //////////////////////////////////
1436
1437 /**
1438  * @ngdoc function
1439  * @name angular.element
1440  * @function
1441  *
1442  * @description
1443  * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
1444  * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if
1445  * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite
1446  * implementation (commonly referred to as jqLite).
1447  *
1448  * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`
1449  * event fired.
1450  *
1451  * jqLite is a tiny, API-compatible subset of jQuery that allows
1452  * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality
1453  * within a very small footprint, so only a subset of the jQuery API - methods, arguments and
1454  * invocation styles - are supported.
1455  *
1456  * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never
1457  * raw DOM references.
1458  *
1459  * ## Angular's jQuery lite provides the following methods:
1460  *
1461  * - [addClass()](http://api.jquery.com/addClass/)
1462  * - [after()](http://api.jquery.com/after/)
1463  * - [append()](http://api.jquery.com/append/)
1464  * - [attr()](http://api.jquery.com/attr/)
1465  * - [bind()](http://api.jquery.com/bind/) - Does not support namespaces
1466  * - [children()](http://api.jquery.com/children/) - Does not support selectors
1467  * - [clone()](http://api.jquery.com/clone/)
1468  * - [contents()](http://api.jquery.com/contents/)
1469  * - [css()](http://api.jquery.com/css/)
1470  * - [data()](http://api.jquery.com/data/)
1471  * - [eq()](http://api.jquery.com/eq/)
1472  * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name
1473  * - [hasClass()](http://api.jquery.com/hasClass/)
1474  * - [html()](http://api.jquery.com/html/)
1475  * - [next()](http://api.jquery.com/next/) - Does not support selectors
1476  * - [parent()](http://api.jquery.com/parent/) - Does not support selectors
1477  * - [prepend()](http://api.jquery.com/prepend/)
1478  * - [prop()](http://api.jquery.com/prop/)
1479  * - [ready()](http://api.jquery.com/ready/)
1480  * - [remove()](http://api.jquery.com/remove/)
1481  * - [removeAttr()](http://api.jquery.com/removeAttr/)
1482  * - [removeClass()](http://api.jquery.com/removeClass/)
1483  * - [removeData()](http://api.jquery.com/removeData/)
1484  * - [replaceWith()](http://api.jquery.com/replaceWith/)
1485  * - [text()](http://api.jquery.com/text/)
1486  * - [toggleClass()](http://api.jquery.com/toggleClass/)
1487  * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
1488  * - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces
1489  * - [val()](http://api.jquery.com/val/)
1490  * - [wrap()](http://api.jquery.com/wrap/)
1491  *
1492  * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
1493  *
1494  * - `controller(name)` - retrieves the controller of the current element or its parent. By default
1495  *   retrieves controller associated with the `ngController` directive. If `name` is provided as
1496  *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
1497  *   `'ngModel'`).
1498  * - `injector()` - retrieves the injector of the current element or its parent.
1499  * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current
1500  *   element or its parent.
1501  * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
1502  *   parent element is reached.
1503  *
1504  * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
1505  * @returns {Object} jQuery object.
1506  */
1507
1508 var jqCache = JQLite.cache = {},
1509     jqName = JQLite.expando = 'ng-' + new Date().getTime(),
1510     jqId = 1,
1511     addEventListenerFn = (window.document.addEventListener
1512       ? function(element, type, fn) {element.addEventListener(type, fn, false);}
1513       : function(element, type, fn) {element.attachEvent('on' + type, fn);}),
1514     removeEventListenerFn = (window.document.removeEventListener
1515       ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
1516       : function(element, type, fn) {element.detachEvent('on' + type, fn); });
1517
1518 function jqNextId() { return ++jqId; }
1519
1520
1521 var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
1522 var MOZ_HACK_REGEXP = /^moz([A-Z])/;
1523
1524 /**
1525  * Converts snake_case to camelCase.
1526  * Also there is special case for Moz prefix starting with upper case letter.
1527  * @param name Name to normalize
1528  */
1529 function camelCase(name) {
1530   return name.
1531     replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
1532       return offset ? letter.toUpperCase() : letter;
1533     }).
1534     replace(MOZ_HACK_REGEXP, 'Moz$1');
1535 }
1536
1537 /////////////////////////////////////////////
1538 // jQuery mutation patch
1539 //
1540 //  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
1541 // $destroy event on all DOM nodes being removed.
1542 //
1543 /////////////////////////////////////////////
1544
1545 function JQLitePatchJQueryRemove(name, dispatchThis) {
1546   var originalJqFn = jQuery.fn[name];
1547   originalJqFn = originalJqFn.$original || originalJqFn;
1548   removePatch.$original = originalJqFn;
1549   jQuery.fn[name] = removePatch;
1550
1551   function removePatch() {
1552     var list = [this],
1553         fireEvent = dispatchThis,
1554         set, setIndex, setLength,
1555         element, childIndex, childLength, children,
1556         fns, events;
1557
1558     while(list.length) {
1559       set = list.shift();
1560       for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
1561         element = jqLite(set[setIndex]);
1562         if (fireEvent) {
1563           element.triggerHandler('$destroy');
1564         } else {
1565           fireEvent = !fireEvent;
1566         }
1567         for(childIndex = 0, childLength = (children = element.children()).length;
1568             childIndex < childLength;
1569             childIndex++) {
1570           list.push(jQuery(children[childIndex]));
1571         }
1572       }
1573     }
1574     return originalJqFn.apply(this, arguments);
1575   }
1576 }
1577
1578 /////////////////////////////////////////////
1579 function JQLite(element) {
1580   if (element instanceof JQLite) {
1581     return element;
1582   }
1583   if (!(this instanceof JQLite)) {
1584     if (isString(element) && element.charAt(0) != '<') {
1585       throw Error('selectors not implemented');
1586     }
1587     return new JQLite(element);
1588   }
1589
1590   if (isString(element)) {
1591     var div = document.createElement('div');
1592     // Read about the NoScope elements here:
1593     // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
1594     div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!
1595     div.removeChild(div.firstChild); // remove the superfluous div
1596     JQLiteAddNodes(this, div.childNodes);
1597     this.remove(); // detach the elements from the temporary DOM div.
1598   } else {
1599     JQLiteAddNodes(this, element);
1600   }
1601 }
1602
1603 function JQLiteClone(element) {
1604   return element.cloneNode(true);
1605 }
1606
1607 function JQLiteDealoc(element){
1608   JQLiteRemoveData(element);
1609   for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
1610     JQLiteDealoc(children[i]);
1611   }
1612 }
1613
1614 function JQLiteUnbind(element, type, fn) {
1615   var events = JQLiteExpandoStore(element, 'events'),
1616       handle = JQLiteExpandoStore(element, 'handle');
1617
1618   if (!handle) return; //no listeners registered
1619
1620   if (isUndefined(type)) {
1621     forEach(events, function(eventHandler, type) {
1622       removeEventListenerFn(element, type, eventHandler);
1623       delete events[type];
1624     });
1625   } else {
1626     if (isUndefined(fn)) {
1627       removeEventListenerFn(element, type, events[type]);
1628       delete events[type];
1629     } else {
1630       arrayRemove(events[type], fn);
1631     }
1632   }
1633 }
1634
1635 function JQLiteRemoveData(element) {
1636   var expandoId = element[jqName],
1637       expandoStore = jqCache[expandoId];
1638
1639   if (expandoStore) {
1640     if (expandoStore.handle) {
1641       expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
1642       JQLiteUnbind(element);
1643     }
1644     delete jqCache[expandoId];
1645     element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
1646   }
1647 }
1648
1649 function JQLiteExpandoStore(element, key, value) {
1650   var expandoId = element[jqName],
1651       expandoStore = jqCache[expandoId || -1];
1652
1653   if (isDefined(value)) {
1654     if (!expandoStore) {
1655       element[jqName] = expandoId = jqNextId();
1656       expandoStore = jqCache[expandoId] = {};
1657     }
1658     expandoStore[key] = value;
1659   } else {
1660     return expandoStore && expandoStore[key];
1661   }
1662 }
1663
1664 function JQLiteData(element, key, value) {
1665   var data = JQLiteExpandoStore(element, 'data'),
1666       isSetter = isDefined(value),
1667       keyDefined = !isSetter && isDefined(key),
1668       isSimpleGetter = keyDefined && !isObject(key);
1669
1670   if (!data && !isSimpleGetter) {
1671     JQLiteExpandoStore(element, 'data', data = {});
1672   }
1673
1674   if (isSetter) {
1675     data[key] = value;
1676   } else {
1677     if (keyDefined) {
1678       if (isSimpleGetter) {
1679         // don't create data in this case.
1680         return data && data[key];
1681       } else {
1682         extend(data, key);
1683       }
1684     } else {
1685       return data;
1686     }
1687   }
1688 }
1689
1690 function JQLiteHasClass(element, selector) {
1691   return ((" " + element.className + " ").replace(/[\n\t]/g, " ").
1692       indexOf( " " + selector + " " ) > -1);
1693 }
1694
1695 function JQLiteRemoveClass(element, cssClasses) {
1696   if (cssClasses) {
1697     forEach(cssClasses.split(' '), function(cssClass) {
1698       element.className = trim(
1699           (" " + element.className + " ")
1700           .replace(/[\n\t]/g, " ")
1701           .replace(" " + trim(cssClass) + " ", " ")
1702       );
1703     });
1704   }
1705 }
1706
1707 function JQLiteAddClass(element, cssClasses) {
1708   if (cssClasses) {
1709     forEach(cssClasses.split(' '), function(cssClass) {
1710       if (!JQLiteHasClass(element, cssClass)) {
1711         element.className = trim(element.className + ' ' + trim(cssClass));
1712       }
1713     });
1714   }
1715 }
1716
1717 function JQLiteAddNodes(root, elements) {
1718   if (elements) {
1719     elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
1720       ? elements
1721       : [ elements ];
1722     for(var i=0; i < elements.length; i++) {
1723       root.push(elements[i]);
1724     }
1725   }
1726 }
1727
1728 function JQLiteController(element, name) {
1729   return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
1730 }
1731
1732 function JQLiteInheritedData(element, name, value) {
1733   element = jqLite(element);
1734
1735   // if element is the document object work with the html element instead
1736   // this makes $(document).scope() possible
1737   if(element[0].nodeType == 9) {
1738     element = element.find('html');
1739   }
1740
1741   while (element.length) {
1742     if (value = element.data(name)) return value;
1743     element = element.parent();
1744   }
1745 }
1746
1747 //////////////////////////////////////////
1748 // Functions which are declared directly.
1749 //////////////////////////////////////////
1750 var JQLitePrototype = JQLite.prototype = {
1751   ready: function(fn) {
1752     var fired = false;
1753
1754     function trigger() {
1755       if (fired) return;
1756       fired = true;
1757       fn();
1758     }
1759
1760     this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9
1761     // we can not use jqLite since we are not done loading and jQuery could be loaded later.
1762     JQLite(window).bind('load', trigger); // fallback to window.onload for others
1763   },
1764   toString: function() {
1765     var value = [];
1766     forEach(this, function(e){ value.push('' + e);});
1767     return '[' + value.join(', ') + ']';
1768   },
1769
1770   eq: function(index) {
1771       return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
1772   },
1773
1774   length: 0,
1775   push: push,
1776   sort: [].sort,
1777   splice: [].splice
1778 };
1779
1780 //////////////////////////////////////////
1781 // Functions iterating getter/setters.
1782 // these functions return self on setter and
1783 // value on get.
1784 //////////////////////////////////////////
1785 var BOOLEAN_ATTR = {};
1786 forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {
1787   BOOLEAN_ATTR[lowercase(value)] = value;
1788 });
1789 var BOOLEAN_ELEMENTS = {};
1790 forEach('input,select,option,textarea,button,form'.split(','), function(value) {
1791   BOOLEAN_ELEMENTS[uppercase(value)] = true;
1792 });
1793
1794 function getBooleanAttrName(element, name) {
1795   // check dom last since we will most likely fail on name
1796   var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
1797
1798   // booleanAttr is here twice to minimize DOM access
1799   return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
1800 }
1801
1802 forEach({
1803   data: JQLiteData,
1804   inheritedData: JQLiteInheritedData,
1805
1806   scope: function(element) {
1807     return JQLiteInheritedData(element, '$scope');
1808   },
1809
1810   controller: JQLiteController ,
1811
1812   injector: function(element) {
1813     return JQLiteInheritedData(element, '$injector');
1814   },
1815
1816   removeAttr: function(element,name) {
1817     element.removeAttribute(name);
1818   },
1819
1820   hasClass: JQLiteHasClass,
1821
1822   css: function(element, name, value) {
1823     name = camelCase(name);
1824
1825     if (isDefined(value)) {
1826       element.style[name] = value;
1827     } else {
1828       var val;
1829
1830       if (msie <= 8) {
1831         // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
1832         val = element.currentStyle && element.currentStyle[name];
1833         if (val === '') val = 'auto';
1834       }
1835
1836       val = val || element.style[name];
1837
1838       if (msie <= 8) {
1839         // jquery weirdness :-/
1840         val = (val === '') ? undefined : val;
1841       }
1842
1843       return  val;
1844     }
1845   },
1846
1847   attr: function(element, name, value){
1848     var lowercasedName = lowercase(name);
1849     if (BOOLEAN_ATTR[lowercasedName]) {
1850       if (isDefined(value)) {
1851         if (!!value) {
1852           element[name] = true;
1853           element.setAttribute(name, lowercasedName);
1854         } else {
1855           element[name] = false;
1856           element.removeAttribute(lowercasedName);
1857         }
1858       } else {
1859         return (element[name] ||
1860                  (element.attributes.getNamedItem(name)|| noop).specified)
1861                ? lowercasedName
1862                : undefined;
1863       }
1864     } else if (isDefined(value)) {
1865       element.setAttribute(name, value);
1866     } else if (element.getAttribute) {
1867       // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
1868       // some elements (e.g. Document) don't have get attribute, so return undefined
1869       var ret = element.getAttribute(name, 2);
1870       // normalize non-existing attributes to undefined (as jQuery)
1871       return ret === null ? undefined : ret;
1872     }
1873   },
1874
1875   prop: function(element, name, value) {
1876     if (isDefined(value)) {
1877       element[name] = value;
1878     } else {
1879       return element[name];
1880     }
1881   },
1882
1883   text: extend((msie < 9)
1884       ? function(element, value) {
1885         if (element.nodeType == 1 /** Element */) {
1886           if (isUndefined(value))
1887             return element.innerText;
1888           element.innerText = value;
1889         } else {
1890           if (isUndefined(value))
1891             return element.nodeValue;
1892           element.nodeValue = value;
1893         }
1894       }
1895       : function(element, value) {
1896         if (isUndefined(value)) {
1897           return element.textContent;
1898         }
1899         element.textContent = value;
1900       }, {$dv:''}),
1901
1902   val: function(element, value) {
1903     if (isUndefined(value)) {
1904       return element.value;
1905     }
1906     element.value = value;
1907   },
1908
1909   html: function(element, value) {
1910     if (isUndefined(value)) {
1911       return element.innerHTML;
1912     }
1913     for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
1914       JQLiteDealoc(childNodes[i]);
1915     }
1916     element.innerHTML = value;
1917   }
1918 }, function(fn, name){
1919   /**
1920    * Properties: writes return selection, reads return first value
1921    */
1922   JQLite.prototype[name] = function(arg1, arg2) {
1923     var i, key;
1924
1925     // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
1926     // in a way that survives minification.
1927     if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {
1928       if (isObject(arg1)) {
1929
1930         // we are a write, but the object properties are the key/values
1931         for(i=0; i < this.length; i++) {
1932           if (fn === JQLiteData) {
1933             // data() takes the whole object in jQuery
1934             fn(this[i], arg1);
1935           } else {
1936             for (key in arg1) {
1937               fn(this[i], key, arg1[key]);
1938             }
1939           }
1940         }
1941         // return self for chaining
1942         return this;
1943       } else {
1944         // we are a read, so read the first child.
1945         if (this.length)
1946           return fn(this[0], arg1, arg2);
1947       }
1948     } else {
1949       // we are a write, so apply to all children
1950       for(i=0; i < this.length; i++) {
1951         fn(this[i], arg1, arg2);
1952       }
1953       // return self for chaining
1954       return this;
1955     }
1956     return fn.$dv;
1957   };
1958 });
1959
1960 function createEventHandler(element, events) {
1961   var eventHandler = function (event, type) {
1962     if (!event.preventDefault) {
1963       event.preventDefault = function() {
1964         event.returnValue = false; //ie
1965       };
1966     }
1967
1968     if (!event.stopPropagation) {
1969       event.stopPropagation = function() {
1970         event.cancelBubble = true; //ie
1971       };
1972     }
1973
1974     if (!event.target) {
1975       event.target = event.srcElement || document;
1976     }
1977
1978     if (isUndefined(event.defaultPrevented)) {
1979       var prevent = event.preventDefault;
1980       event.preventDefault = function() {
1981         event.defaultPrevented = true;
1982         prevent.call(event);
1983       };
1984       event.defaultPrevented = false;
1985     }
1986
1987     event.isDefaultPrevented = function() {
1988       return event.defaultPrevented;
1989     };
1990
1991     forEach(events[type || event.type], function(fn) {
1992       fn.call(element, event);
1993     });
1994
1995     // Remove monkey-patched methods (IE),
1996     // as they would cause memory leaks in IE8.
1997     if (msie <= 8) {
1998       // IE7/8 does not allow to delete property on native object
1999       event.preventDefault = null;
2000       event.stopPropagation = null;
2001       event.isDefaultPrevented = null;
2002     } else {
2003       // It shouldn't affect normal browsers (native methods are defined on prototype).
2004       delete event.preventDefault;
2005       delete event.stopPropagation;
2006       delete event.isDefaultPrevented;
2007     }
2008   };
2009   eventHandler.elem = element;
2010   return eventHandler;
2011 }
2012
2013 //////////////////////////////////////////
2014 // Functions iterating traversal.
2015 // These functions chain results into a single
2016 // selector.
2017 //////////////////////////////////////////
2018 forEach({
2019   removeData: JQLiteRemoveData,
2020
2021   dealoc: JQLiteDealoc,
2022
2023   bind: function bindFn(element, type, fn){
2024     var events = JQLiteExpandoStore(element, 'events'),
2025         handle = JQLiteExpandoStore(element, 'handle');
2026
2027     if (!events) JQLiteExpandoStore(element, 'events', events = {});
2028     if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
2029
2030     forEach(type.split(' '), function(type){
2031       var eventFns = events[type];
2032
2033       if (!eventFns) {
2034         if (type == 'mouseenter' || type == 'mouseleave') {
2035           var contains = document.body.contains || document.body.compareDocumentPosition ?
2036           function( a, b ) {
2037             var adown = a.nodeType === 9 ? a.documentElement : a,
2038             bup = b && b.parentNode;
2039             return a === bup || !!( bup && bup.nodeType === 1 && (
2040               adown.contains ?
2041               adown.contains( bup ) :
2042               a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
2043               ));
2044             } :
2045             function( a, b ) {
2046               if ( b ) {
2047                 while ( (b = b.parentNode) ) {
2048                   if ( b === a ) {
2049                     return true;
2050                   }
2051                 }
2052               }
2053               return false;
2054             };
2055
2056           events[type] = [];
2057
2058           // Refer to jQuery's implementation of mouseenter & mouseleave
2059           // Read about mouseenter and mouseleave:
2060           // http://www.quirksmode.org/js/events_mouse.html#link8
2061           var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"}          
2062           bindFn(element, eventmap[type], function(event) {
2063             var ret, target = this, related = event.relatedTarget;
2064             // For mousenter/leave call the handler if related is outside the target.
2065             // NB: No relatedTarget if the mouse left/entered the browser window
2066             if ( !related || (related !== target && !contains(target, related)) ){
2067               handle(event, type);
2068             }
2069
2070           });
2071
2072         } else {
2073           addEventListenerFn(element, type, handle);
2074           events[type] = [];
2075         }
2076         eventFns = events[type]
2077       }
2078       eventFns.push(fn);
2079     });
2080   },
2081
2082   unbind: JQLiteUnbind,
2083
2084   replaceWith: function(element, replaceNode) {
2085     var index, parent = element.parentNode;
2086     JQLiteDealoc(element);
2087     forEach(new JQLite(replaceNode), function(node){
2088       if (index) {
2089         parent.insertBefore(node, index.nextSibling);
2090       } else {
2091         parent.replaceChild(node, element);
2092       }
2093       index = node;
2094     });
2095   },
2096
2097   children: function(element) {
2098     var children = [];
2099     forEach(element.childNodes, function(element){
2100       if (element.nodeType === 1)
2101         children.push(element);
2102     });
2103     return children;
2104   },
2105
2106   contents: function(element) {
2107     return element.childNodes || [];
2108   },
2109
2110   append: function(element, node) {
2111     forEach(new JQLite(node), function(child){
2112       if (element.nodeType === 1)
2113         element.appendChild(child);
2114     });
2115   },
2116
2117   prepend: function(element, node) {
2118     if (element.nodeType === 1) {
2119       var index = element.firstChild;
2120       forEach(new JQLite(node), function(child){
2121         if (index) {
2122           element.insertBefore(child, index);
2123         } else {
2124           element.appendChild(child);
2125           index = child;
2126         }
2127       });
2128     }
2129   },
2130
2131   wrap: function(element, wrapNode) {
2132     wrapNode = jqLite(wrapNode)[0];
2133     var parent = element.parentNode;
2134     if (parent) {
2135       parent.replaceChild(wrapNode, element);
2136     }
2137     wrapNode.appendChild(element);
2138   },
2139
2140   remove: function(element) {
2141     JQLiteDealoc(element);
2142     var parent = element.parentNode;
2143     if (parent) parent.removeChild(element);
2144   },
2145
2146   after: function(element, newElement) {
2147     var index = element, parent = element.parentNode;
2148     forEach(new JQLite(newElement), function(node){
2149       parent.insertBefore(node, index.nextSibling);
2150       index = node;
2151     });
2152   },
2153
2154   addClass: JQLiteAddClass,
2155   removeClass: JQLiteRemoveClass,
2156
2157   toggleClass: function(element, selector, condition) {
2158     if (isUndefined(condition)) {
2159       condition = !JQLiteHasClass(element, selector);
2160     }
2161     (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);
2162   },
2163
2164   parent: function(element) {
2165     var parent = element.parentNode;
2166     return parent && parent.nodeType !== 11 ? parent : null;
2167   },
2168
2169   next: function(element) {
2170     if (element.nextElementSibling) {
2171       return element.nextElementSibling;
2172     }
2173
2174     // IE8 doesn't have nextElementSibling
2175     var elm = element.nextSibling;
2176     while (elm != null && elm.nodeType !== 1) {
2177       elm = elm.nextSibling;
2178     }
2179     return elm;
2180   },
2181
2182   find: function(element, selector) {
2183     return element.getElementsByTagName(selector);
2184   },
2185
2186   clone: JQLiteClone,
2187
2188   triggerHandler: function(element, eventName) {
2189     var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
2190
2191     forEach(eventFns, function(fn) {
2192       fn.call(element, null);
2193     });
2194   }
2195 }, function(fn, name){
2196   /**
2197    * chaining functions
2198    */
2199   JQLite.prototype[name] = function(arg1, arg2) {
2200     var value;
2201     for(var i=0; i < this.length; i++) {
2202       if (value == undefined) {
2203         value = fn(this[i], arg1, arg2);
2204         if (value !== undefined) {
2205           // any function which returns a value needs to be wrapped
2206           value = jqLite(value);
2207         }
2208       } else {
2209         JQLiteAddNodes(value, fn(this[i], arg1, arg2));
2210       }
2211     }
2212     return value == undefined ? this : value;
2213   };
2214 });
2215
2216 /**
2217  * Computes a hash of an 'obj'.
2218  * Hash of a:
2219  *  string is string
2220  *  number is number as string
2221  *  object is either result of calling $$hashKey function on the object or uniquely generated id,
2222  *         that is also assigned to the $$hashKey property of the object.
2223  *
2224  * @param obj
2225  * @returns {string} hash string such that the same input will have the same hash string.
2226  *         The resulting string key is in 'type:hashKey' format.
2227  */
2228 function hashKey(obj) {
2229   var objType = typeof obj,
2230       key;
2231
2232   if (objType == 'object' && obj !== null) {
2233     if (typeof (key = obj.$$hashKey) == 'function') {
2234       // must invoke on object to keep the right this
2235       key = obj.$$hashKey();
2236     } else if (key === undefined) {
2237       key = obj.$$hashKey = nextUid();
2238     }
2239   } else {
2240     key = obj;
2241   }
2242
2243   return objType + ':' + key;
2244 }
2245
2246 /**
2247  * HashMap which can use objects as keys
2248  */
2249 function HashMap(array){
2250   forEach(array, this.put, this);
2251 }
2252 HashMap.prototype = {
2253   /**
2254    * Store key value pair
2255    * @param key key to store can be any type
2256    * @param value value to store can be any type
2257    */
2258   put: function(key, value) {
2259     this[hashKey(key)] = value;
2260   },
2261
2262   /**
2263    * @param key
2264    * @returns the value for the key
2265    */
2266   get: function(key) {
2267     return this[hashKey(key)];
2268   },
2269
2270   /**
2271    * Remove the key/value pair
2272    * @param key
2273    */
2274   remove: function(key) {
2275     var value = this[key = hashKey(key)];
2276     delete this[key];
2277     return value;
2278   }
2279 };
2280
2281 /**
2282  * A map where multiple values can be added to the same key such that they form a queue.
2283  * @returns {HashQueueMap}
2284  */
2285 function HashQueueMap() {}
2286 HashQueueMap.prototype = {
2287   /**
2288    * Same as array push, but using an array as the value for the hash
2289    */
2290   push: function(key, value) {
2291     var array = this[key = hashKey(key)];
2292     if (!array) {
2293       this[key] = [value];
2294     } else {
2295       array.push(value);
2296     }
2297   },
2298
2299   /**
2300    * Same as array shift, but using an array as the value for the hash
2301    */
2302   shift: function(key) {
2303     var array = this[key = hashKey(key)];
2304     if (array) {
2305       if (array.length == 1) {
2306         delete this[key];
2307         return array[0];
2308       } else {
2309         return array.shift();
2310       }
2311     }
2312   },
2313
2314   /**
2315    * return the first item without deleting it
2316    */
2317   peek: function(key) {
2318     var array = this[hashKey(key)];
2319     if (array) {
2320     return array[0];
2321     }
2322   }
2323 };
2324
2325 /**
2326  * @ngdoc function
2327  * @name angular.injector
2328  * @function
2329  *
2330  * @description
2331  * Creates an injector function that can be used for retrieving services as well as for
2332  * dependency injection (see {@link guide/di dependency injection}).
2333  *
2334
2335  * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
2336  *        {@link angular.module}. The `ng` module must be explicitly added.
2337  * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.
2338  *
2339  * @example
2340  * Typical usage
2341  * <pre>
2342  *   // create an injector
2343  *   var $injector = angular.injector(['ng']);
2344  *
2345  *   // use the injector to kick off your application
2346  *   // use the type inference to auto inject arguments, or use implicit injection
2347  *   $injector.invoke(function($rootScope, $compile, $document){
2348  *     $compile($document)($rootScope);
2349  *     $rootScope.$digest();
2350  *   });
2351  * </pre>
2352  */
2353
2354
2355 /**
2356  * @ngdoc overview
2357  * @name AUTO
2358  * @description
2359  *
2360  * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
2361  */
2362
2363 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
2364 var FN_ARG_SPLIT = /,/;
2365 var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
2366 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
2367 function annotate(fn) {
2368   var $inject,
2369       fnText,
2370       argDecl,
2371       last;
2372
2373   if (typeof fn == 'function') {
2374     if (!($inject = fn.$inject)) {
2375       $inject = [];
2376       fnText = fn.toString().replace(STRIP_COMMENTS, '');
2377       argDecl = fnText.match(FN_ARGS);
2378       forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
2379         arg.replace(FN_ARG, function(all, underscore, name){
2380           $inject.push(name);
2381         });
2382       });
2383       fn.$inject = $inject;
2384     }
2385   } else if (isArray(fn)) {
2386     last = fn.length - 1;
2387     assertArgFn(fn[last], 'fn');
2388     $inject = fn.slice(0, last);
2389   } else {
2390     assertArgFn(fn, 'fn', true);
2391   }
2392   return $inject;
2393 }
2394
2395 ///////////////////////////////////////
2396
2397 /**
2398  * @ngdoc object
2399  * @name AUTO.$injector
2400  * @function
2401  *
2402  * @description
2403  *
2404  * `$injector` is used to retrieve object instances as defined by
2405  * {@link AUTO.$provide provider}, instantiate types, invoke methods,
2406  * and load modules.
2407  *
2408  * The following always holds true:
2409  *
2410  * <pre>
2411  *   var $injector = angular.injector();
2412  *   expect($injector.get('$injector')).toBe($injector);
2413  *   expect($injector.invoke(function($injector){
2414  *     return $injector;
2415  *   }).toBe($injector);
2416  * </pre>
2417  *
2418  * # Injection Function Annotation
2419  *
2420  * JavaScript does not have annotations, and annotations are needed for dependency injection. The
2421  * following are all valid ways of annotating function with injection arguments and are equivalent.
2422  *
2423  * <pre>
2424  *   // inferred (only works if code not minified/obfuscated)
2425  *   $injector.invoke(function(serviceA){});
2426  *
2427  *   // annotated
2428  *   function explicit(serviceA) {};
2429  *   explicit.$inject = ['serviceA'];
2430  *   $injector.invoke(explicit);
2431  *
2432  *   // inline
2433  *   $injector.invoke(['serviceA', function(serviceA){}]);
2434  * </pre>
2435  *
2436  * ## Inference
2437  *
2438  * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be
2439  * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation
2440  * tools since these tools change the argument names.
2441  *
2442  * ## `$inject` Annotation
2443  * By adding a `$inject` property onto a function the injection parameters can be specified.
2444  *
2445  * ## Inline
2446  * As an array of injection names, where the last item in the array is the function to call.
2447  */
2448
2449 /**
2450  * @ngdoc method
2451  * @name AUTO.$injector#get
2452  * @methodOf AUTO.$injector
2453  *
2454  * @description
2455  * Return an instance of the service.
2456  *
2457  * @param {string} name The name of the instance to retrieve.
2458  * @return {*} The instance.
2459  */
2460
2461 /**
2462  * @ngdoc method
2463  * @name AUTO.$injector#invoke
2464  * @methodOf AUTO.$injector
2465  *
2466  * @description
2467  * Invoke the method and supply the method arguments from the `$injector`.
2468  *
2469  * @param {!function} fn The function to invoke. The function arguments come form the function annotation.
2470  * @param {Object=} self The `this` for the invoked method.
2471  * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before
2472  *   the `$injector` is consulted.
2473  * @returns {*} the value returned by the invoked `fn` function.
2474  */
2475
2476 /**
2477  * @ngdoc method
2478  * @name AUTO.$injector#instantiate
2479  * @methodOf AUTO.$injector
2480  * @description
2481  * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies
2482  * all of the arguments to the constructor function as specified by the constructor annotation.
2483  *
2484  * @param {function} Type Annotated constructor function.
2485  * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before
2486  *   the `$injector` is consulted.
2487  * @returns {Object} new instance of `Type`.
2488  */
2489
2490 /**
2491  * @ngdoc method
2492  * @name AUTO.$injector#annotate
2493  * @methodOf AUTO.$injector
2494  *
2495  * @description
2496  * Returns an array of service names which the function is requesting for injection. This API is used by the injector
2497  * to determine which services need to be injected into the function when the function is invoked. There are three
2498  * ways in which the function can be annotated with the needed dependencies.
2499  *
2500  * # Argument names
2501  *
2502  * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting
2503  * the function into a string using `toString()` method and extracting the argument names.
2504  * <pre>
2505  *   // Given
2506  *   function MyController($scope, $route) {
2507  *     // ...
2508  *   }
2509  *
2510  *   // Then
2511  *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
2512  * </pre>
2513  *
2514  * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
2515  * are supported.
2516  *
2517  * # The `$inject` property
2518  *
2519  * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
2520  * services to be injected into the function.
2521  * <pre>
2522  *   // Given
2523  *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
2524  *     // ...
2525  *   }
2526  *   // Define function dependencies
2527  *   MyController.$inject = ['$scope', '$route'];
2528  *
2529  *   // Then
2530  *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
2531  * </pre>
2532  *
2533  * # The array notation
2534  *
2535  * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very
2536  * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives
2537  * minification is a better choice:
2538  *
2539  * <pre>
2540  *   // We wish to write this (not minification / obfuscation safe)
2541  *   injector.invoke(function($compile, $rootScope) {
2542  *     // ...
2543  *   });
2544  *
2545  *   // We are forced to write break inlining
2546  *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
2547  *     // ...
2548  *   };
2549  *   tmpFn.$inject = ['$compile', '$rootScope'];
2550  *   injector.invoke(tmpFn);
2551  *
2552  *   // To better support inline function the inline annotation is supported
2553  *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
2554  *     // ...
2555  *   }]);
2556  *
2557  *   // Therefore
2558  *   expect(injector.annotate(
2559  *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
2560  *    ).toEqual(['$compile', '$rootScope']);
2561  * </pre>
2562  *
2563  * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described
2564  *   above.
2565  *
2566  * @returns {Array.<string>} The names of the services which the function requires.
2567  */
2568
2569
2570
2571
2572 /**
2573  * @ngdoc object
2574  * @name AUTO.$provide
2575  *
2576  * @description
2577  *
2578  * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.
2579  * The providers share the same name as the instance they create with `Provider` suffixed to them.
2580  *
2581  * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of
2582  * a service. The Provider can have additional methods which would allow for configuration of the provider.
2583  *
2584  * <pre>
2585  *   function GreetProvider() {
2586  *     var salutation = 'Hello';
2587  *
2588  *     this.salutation = function(text) {
2589  *       salutation = text;
2590  *     };
2591  *
2592  *     this.$get = function() {
2593  *       return function (name) {
2594  *         return salutation + ' ' + name + '!';
2595  *       };
2596  *     };
2597  *   }
2598  *
2599  *   describe('Greeter', function(){
2600  *
2601  *     beforeEach(module(function($provide) {
2602  *       $provide.provider('greet', GreetProvider);
2603  *     }));
2604  *
2605  *     it('should greet', inject(function(greet) {
2606  *       expect(greet('angular')).toEqual('Hello angular!');
2607  *     }));
2608  *
2609  *     it('should allow configuration of salutation', function() {
2610  *       module(function(greetProvider) {
2611  *         greetProvider.salutation('Ahoj');
2612  *       });
2613  *       inject(function(greet) {
2614  *         expect(greet('angular')).toEqual('Ahoj angular!');
2615  *       });
2616  *     });
2617  * </pre>
2618  */
2619
2620 /**
2621  * @ngdoc method
2622  * @name AUTO.$provide#provider
2623  * @methodOf AUTO.$provide
2624  * @description
2625  *
2626  * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.
2627  *
2628  * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.
2629  * @param {(Object|function())} provider If the provider is:
2630  *
2631  *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
2632  *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.
2633  *   - `Constructor`: a new instance of the provider will be created using
2634  *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.
2635  *
2636  * @returns {Object} registered provider instance
2637  */
2638
2639 /**
2640  * @ngdoc method
2641  * @name AUTO.$provide#factory
2642  * @methodOf AUTO.$provide
2643  * @description
2644  *
2645  * A short hand for configuring services if only `$get` method is required.
2646  *
2647  * @param {string} name The name of the instance.
2648  * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for
2649  * `$provide.provider(name, {$get: $getFn})`.
2650  * @returns {Object} registered provider instance
2651  */
2652
2653
2654 /**
2655  * @ngdoc method
2656  * @name AUTO.$provide#service
2657  * @methodOf AUTO.$provide
2658  * @description
2659  *
2660  * A short hand for registering service of given class.
2661  *
2662  * @param {string} name The name of the instance.
2663  * @param {Function} constructor A class (constructor function) that will be instantiated.
2664  * @returns {Object} registered provider instance
2665  */
2666
2667
2668 /**
2669  * @ngdoc method
2670  * @name AUTO.$provide#value
2671  * @methodOf AUTO.$provide
2672  * @description
2673  *
2674  * A short hand for configuring services if the `$get` method is a constant.
2675  *
2676  * @param {string} name The name of the instance.
2677  * @param {*} value The value.
2678  * @returns {Object} registered provider instance
2679  */
2680
2681
2682 /**
2683  * @ngdoc method
2684  * @name AUTO.$provide#constant
2685  * @methodOf AUTO.$provide
2686  * @description
2687  *
2688  * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected
2689  * into configuration function (other modules) and it is not interceptable by
2690  * {@link AUTO.$provide#decorator decorator}.
2691  *
2692  * @param {string} name The name of the constant.
2693  * @param {*} value The constant value.
2694  * @returns {Object} registered instance
2695  */
2696
2697
2698 /**
2699  * @ngdoc method
2700  * @name AUTO.$provide#decorator
2701  * @methodOf AUTO.$provide
2702  * @description
2703  *
2704  * Decoration of service, allows the decorator to intercept the service instance creation. The
2705  * returned instance may be the original instance, or a new instance which delegates to the
2706  * original instance.
2707  *
2708  * @param {string} name The name of the service to decorate.
2709  * @param {function()} decorator This function will be invoked when the service needs to be
2710  *    instantiated. The function is called using the {@link AUTO.$injector#invoke
2711  *    injector.invoke} method and is therefore fully injectable. Local injection arguments:
2712  *
2713  *    * `$delegate` - The original service instance, which can be monkey patched, configured,
2714  *      decorated or delegated to.
2715  */
2716
2717
2718 function createInjector(modulesToLoad) {
2719   var INSTANTIATING = {},
2720       providerSuffix = 'Provider',
2721       path = [],
2722       loadedModules = new HashMap(),
2723       providerCache = {
2724         $provide: {
2725             provider: supportObject(provider),
2726             factory: supportObject(factory),
2727             service: supportObject(service),
2728             value: supportObject(value),
2729             constant: supportObject(constant),
2730             decorator: decorator
2731           }
2732       },
2733       providerInjector = createInternalInjector(providerCache, function() {
2734         throw Error("Unknown provider: " + path.join(' <- '));
2735       }),
2736       instanceCache = {},
2737       instanceInjector = (instanceCache.$injector =
2738           createInternalInjector(instanceCache, function(servicename) {
2739             var provider = providerInjector.get(servicename + providerSuffix);
2740             return instanceInjector.invoke(provider.$get, provider);
2741           }));
2742
2743
2744   forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
2745
2746   return instanceInjector;
2747
2748   ////////////////////////////////////
2749   // $provider
2750   ////////////////////////////////////
2751
2752   function supportObject(delegate) {
2753     return function(key, value) {
2754       if (isObject(key)) {
2755         forEach(key, reverseParams(delegate));
2756       } else {
2757         return delegate(key, value);
2758       }
2759     }
2760   }
2761
2762   function provider(name, provider_) {
2763     if (isFunction(provider_) || isArray(provider_)) {
2764       provider_ = providerInjector.instantiate(provider_);
2765     }
2766     if (!provider_.$get) {
2767       throw Error('Provider ' + name + ' must define $get factory method.');
2768     }
2769     return providerCache[name + providerSuffix] = provider_;
2770   }
2771
2772   function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
2773
2774   function service(name, constructor) {
2775     return factory(name, ['$injector', function($injector) {
2776       return $injector.instantiate(constructor);
2777     }]);
2778   }
2779
2780   function value(name, value) { return factory(name, valueFn(value)); }
2781
2782   function constant(name, value) {
2783     providerCache[name] = value;
2784     instanceCache[name] = value;
2785   }
2786
2787   function decorator(serviceName, decorFn) {
2788     var origProvider = providerInjector.get(serviceName + providerSuffix),
2789         orig$get = origProvider.$get;
2790
2791     origProvider.$get = function() {
2792       var origInstance = instanceInjector.invoke(orig$get, origProvider);
2793       return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
2794     };
2795   }
2796
2797   ////////////////////////////////////
2798   // Module Loading
2799   ////////////////////////////////////
2800   function loadModules(modulesToLoad){
2801     var runBlocks = [];
2802     forEach(modulesToLoad, function(module) {
2803       if (loadedModules.get(module)) return;
2804       loadedModules.put(module, true);
2805       if (isString(module)) {
2806         var moduleFn = angularModule(module);
2807         runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
2808
2809         try {
2810           for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
2811             var invokeArgs = invokeQueue[i],
2812                 provider = invokeArgs[0] == '$injector'
2813                     ? providerInjector
2814                     : providerInjector.get(invokeArgs[0]);
2815
2816             provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
2817           }
2818         } catch (e) {
2819           if (e.message) e.message += ' from ' + module;
2820           throw e;
2821         }
2822       } else if (isFunction(module)) {
2823         try {
2824           runBlocks.push(providerInjector.invoke(module));
2825         } catch (e) {
2826           if (e.message) e.message += ' from ' + module;
2827           throw e;
2828         }
2829       } else if (isArray(module)) {
2830         try {
2831           runBlocks.push(providerInjector.invoke(module));
2832         } catch (e) {
2833           if (e.message) e.message += ' from ' + String(module[module.length - 1]);
2834           throw e;
2835         }
2836       } else {
2837         assertArgFn(module, 'module');
2838       }
2839     });
2840     return runBlocks;
2841   }
2842
2843   ////////////////////////////////////
2844   // internal Injector
2845   ////////////////////////////////////
2846
2847   function createInternalInjector(cache, factory) {
2848
2849     function getService(serviceName) {
2850       if (typeof serviceName !== 'string') {
2851         throw Error('Service name expected');
2852       }
2853       if (cache.hasOwnProperty(serviceName)) {
2854         if (cache[serviceName] === INSTANTIATING) {
2855           throw Error('Circular dependency: ' + path.join(' <- '));
2856         }
2857         return cache[serviceName];
2858       } else {
2859         try {
2860           path.unshift(serviceName);
2861           cache[serviceName] = INSTANTIATING;
2862           return cache[serviceName] = factory(serviceName);
2863         } finally {
2864           path.shift();
2865         }
2866       }
2867     }
2868
2869     function invoke(fn, self, locals){
2870       var args = [],
2871           $inject = annotate(fn),
2872           length, i,
2873           key;
2874
2875       for(i = 0, length = $inject.length; i < length; i++) {
2876         key = $inject[i];
2877         args.push(
2878           locals && locals.hasOwnProperty(key)
2879           ? locals[key]
2880           : getService(key)
2881         );
2882       }
2883       if (!fn.$inject) {
2884         // this means that we must be an array.
2885         fn = fn[length];
2886       }
2887
2888
2889       // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
2890       switch (self ? -1 : args.length) {
2891         case  0: return fn();
2892         case  1: return fn(args[0]);
2893         case  2: return fn(args[0], args[1]);
2894         case  3: return fn(args[0], args[1], args[2]);
2895         case  4: return fn(args[0], args[1], args[2], args[3]);
2896         case  5: return fn(args[0], args[1], args[2], args[3], args[4]);