You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by ma...@apache.org on 2014/05/28 21:05:13 UTC

[04/29] Upgrade Aurora UI to bootstrap3

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/3a992e2c/3rdparty/javascript/bower_components/smart-table/smart-table-module/lib/angular/angular.js
----------------------------------------------------------------------
diff --git a/3rdparty/javascript/bower_components/smart-table/smart-table-module/lib/angular/angular.js b/3rdparty/javascript/bower_components/smart-table/smart-table-module/lib/angular/angular.js
new file mode 100644
index 0000000..a1eabdf
--- /dev/null
+++ b/3rdparty/javascript/bower_components/smart-table/smart-table-module/lib/angular/angular.js
@@ -0,0 +1,15018 @@
+/**
+ * @license AngularJS v1.0.7
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function (window, document, undefined) {
+    'use strict';
+
+////////////////////////////////////
+
+    /**
+     * @ngdoc function
+     * @name angular.lowercase
+     * @function
+     *
+     * @description Converts the specified string to lowercase.
+     * @param {string} string String to be converted to lowercase.
+     * @returns {string} Lowercased string.
+     */
+    var lowercase = function (string) {
+        return isString(string) ? string.toLowerCase() : string;
+    };
+
+
+    /**
+     * @ngdoc function
+     * @name angular.uppercase
+     * @function
+     *
+     * @description Converts the specified string to uppercase.
+     * @param {string} string String to be converted to uppercase.
+     * @returns {string} Uppercased string.
+     */
+    var uppercase = function (string) {
+        return isString(string) ? string.toUpperCase() : string;
+    };
+
+
+    var manualLowercase = function (s) {
+        return isString(s)
+            ? s.replace(/[A-Z]/g, function (ch) {
+            return String.fromCharCode(ch.charCodeAt(0) | 32);
+        })
+            : s;
+    };
+    var manualUppercase = function (s) {
+        return isString(s)
+            ? s.replace(/[a-z]/g, function (ch) {
+            return String.fromCharCode(ch.charCodeAt(0) & ~32);
+        })
+            : s;
+    };
+
+
+// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
+// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
+// with correct but slower alternatives.
+    if ('i' !== 'I'.toLowerCase()) {
+        lowercase = manualLowercase;
+        uppercase = manualUppercase;
+    }
+
+
+    var /** holds major version number for IE or NaN for real browsers */
+            msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
+        jqLite,           // delay binding since jQuery could be loaded after us.
+        jQuery,           // delay binding
+        slice = [].slice,
+        push = [].push,
+        toString = Object.prototype.toString,
+
+        /** @name angular */
+            angular = window.angular || (window.angular = {}),
+        angularModule,
+        nodeName_,
+        uid = ['0', '0', '0'];
+
+
+    /**
+     * @private
+     * @param {*} obj
+     * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
+     */
+    function isArrayLike(obj) {
+        if (!obj || (typeof obj.length !== 'number')) return false;
+
+        // We have on object which has length property. Should we treat it as array?
+        if (typeof obj.hasOwnProperty != 'function' &&
+            typeof obj.constructor != 'function') {
+            // This is here for IE8: it is a bogus object treat it as array;
+            return true;
+        } else {
+            return obj instanceof JQLite ||                      // JQLite
+                (jQuery && obj instanceof jQuery) ||          // jQuery
+                toString.call(obj) !== '[object Object]' ||   // some browser native object
+                typeof obj.callee === 'function';              // arguments (on IE8 looks like regular obj)
+        }
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.forEach
+     * @function
+     *
+     * @description
+     * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
+     * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
+     * is the value of an object property or an array element and `key` is the object property key or
+     * array element index. Specifying a `context` for the function is optional.
+     *
+     * Note: this function was previously known as `angular.foreach`.
+     *
+     <pre>
+     var values = {name: 'misko', gender: 'male'};
+     var log = [];
+     angular.forEach(values, function(value, key){
+       this.push(key + ': ' + value);
+     }, log);
+     expect(log).toEqual(['name: misko', 'gender:male']);
+     </pre>
+     *
+     * @param {Object|Array} obj Object to iterate over.
+     * @param {Function} iterator Iterator function.
+     * @param {Object=} context Object to become context (`this`) for the iterator function.
+     * @returns {Object|Array} Reference to `obj`.
+     */
+    function forEach(obj, iterator, context) {
+        var key;
+        if (obj) {
+            if (isFunction(obj)) {
+                for (key in obj) {
+                    if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
+                        iterator.call(context, obj[key], key);
+                    }
+                }
+            } else if (obj.forEach && obj.forEach !== forEach) {
+                obj.forEach(iterator, context);
+            } else if (isArrayLike(obj)) {
+                for (key = 0; key < obj.length; key++)
+                    iterator.call(context, obj[key], key);
+            } else {
+                for (key in obj) {
+                    if (obj.hasOwnProperty(key)) {
+                        iterator.call(context, obj[key], key);
+                    }
+                }
+            }
+        }
+        return obj;
+    }
+
+    function sortedKeys(obj) {
+        var keys = [];
+        for (var key in obj) {
+            if (obj.hasOwnProperty(key)) {
+                keys.push(key);
+            }
+        }
+        return keys.sort();
+    }
+
+    function forEachSorted(obj, iterator, context) {
+        var keys = sortedKeys(obj);
+        for (var i = 0; i < keys.length; i++) {
+            iterator.call(context, obj[keys[i]], keys[i]);
+        }
+        return keys;
+    }
+
+
+    /**
+     * when using forEach the params are value, key, but it is often useful to have key, value.
+     * @param {function(string, *)} iteratorFn
+     * @returns {function(*, string)}
+     */
+    function reverseParams(iteratorFn) {
+        return function (value, key) {
+            iteratorFn(key, value)
+        };
+    }
+
+    /**
+     * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
+     * characters such as '012ABC'. The reason why we are not using simply a number counter is that
+     * the number string gets longer over time, and it can also overflow, where as the nextId
+     * will grow much slower, it is a string, and it will never overflow.
+     *
+     * @returns an unique alpha-numeric string
+     */
+    function nextUid() {
+        var index = uid.length;
+        var digit;
+
+        while (index) {
+            index--;
+            digit = uid[index].charCodeAt(0);
+            if (digit == 57 /*'9'*/) {
+                uid[index] = 'A';
+                return uid.join('');
+            }
+            if (digit == 90  /*'Z'*/) {
+                uid[index] = '0';
+            } else {
+                uid[index] = String.fromCharCode(digit + 1);
+                return uid.join('');
+            }
+        }
+        uid.unshift('0');
+        return uid.join('');
+    }
+
+
+    /**
+     * Set or clear the hashkey for an object.
+     * @param obj object
+     * @param h the hashkey (!truthy to delete the hashkey)
+     */
+    function setHashKey(obj, h) {
+        if (h) {
+            obj.$$hashKey = h;
+        }
+        else {
+            delete obj.$$hashKey;
+        }
+    }
+
+    /**
+     * @ngdoc function
+     * @name angular.extend
+     * @function
+     *
+     * @description
+     * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
+     * to `dst`. You can specify multiple `src` objects.
+     *
+     * @param {Object} dst Destination object.
+     * @param {...Object} src Source object(s).
+     * @returns {Object} Reference to `dst`.
+     */
+    function extend(dst) {
+        var h = dst.$$hashKey;
+        forEach(arguments, function (obj) {
+            if (obj !== dst) {
+                forEach(obj, function (value, key) {
+                    dst[key] = value;
+                });
+            }
+        });
+
+        setHashKey(dst, h);
+        return dst;
+    }
+
+    function int(str) {
+        return parseInt(str, 10);
+    }
+
+
+    function inherit(parent, extra) {
+        return extend(new (extend(function () {
+        }, {prototype: parent}))(), extra);
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.noop
+     * @function
+     *
+     * @description
+     * A function that performs no operations. This function can be useful when writing code in the
+     * functional style.
+     <pre>
+     function foo(callback) {
+       var result = calculateResult();
+       (callback || angular.noop)(result);
+     }
+     </pre>
+     */
+    function noop() {
+    }
+
+    noop.$inject = [];
+
+
+    /**
+     * @ngdoc function
+     * @name angular.identity
+     * @function
+     *
+     * @description
+     * A function that returns its first argument. This function is useful when writing code in the
+     * functional style.
+     *
+     <pre>
+     function transformer(transformationFn, value) {
+       return (transformationFn || identity)(value);
+     };
+     </pre>
+     */
+    function identity($) {
+        return $;
+    }
+
+    identity.$inject = [];
+
+
+    function valueFn(value) {
+        return function () {
+            return value;
+        };
+    }
+
+    /**
+     * @ngdoc function
+     * @name angular.isUndefined
+     * @function
+     *
+     * @description
+     * Determines if a reference is undefined.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is undefined.
+     */
+    function isUndefined(value) {
+        return typeof value == 'undefined';
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.isDefined
+     * @function
+     *
+     * @description
+     * Determines if a reference is defined.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is defined.
+     */
+    function isDefined(value) {
+        return typeof value != 'undefined';
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.isObject
+     * @function
+     *
+     * @description
+     * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
+     * considered to be objects.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is an `Object` but not `null`.
+     */
+    function isObject(value) {
+        return value != null && typeof value == 'object';
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.isString
+     * @function
+     *
+     * @description
+     * Determines if a reference is a `String`.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is a `String`.
+     */
+    function isString(value) {
+        return typeof value == 'string';
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.isNumber
+     * @function
+     *
+     * @description
+     * Determines if a reference is a `Number`.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is a `Number`.
+     */
+    function isNumber(value) {
+        return typeof value == 'number';
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.isDate
+     * @function
+     *
+     * @description
+     * Determines if a value is a date.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is a `Date`.
+     */
+    function isDate(value) {
+        return toString.apply(value) == '[object Date]';
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.isArray
+     * @function
+     *
+     * @description
+     * Determines if a reference is an `Array`.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is an `Array`.
+     */
+    function isArray(value) {
+        return toString.apply(value) == '[object Array]';
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.isFunction
+     * @function
+     *
+     * @description
+     * Determines if a reference is a `Function`.
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is a `Function`.
+     */
+    function isFunction(value) {
+        return typeof value == 'function';
+    }
+
+
+    /**
+     * Checks if `obj` is a window object.
+     *
+     * @private
+     * @param {*} obj Object to check
+     * @returns {boolean} True if `obj` is a window obj.
+     */
+    function isWindow(obj) {
+        return obj && obj.document && obj.location && obj.alert && obj.setInterval;
+    }
+
+
+    function isScope(obj) {
+        return obj && obj.$evalAsync && obj.$watch;
+    }
+
+
+    function isFile(obj) {
+        return toString.apply(obj) === '[object File]';
+    }
+
+
+    function isBoolean(value) {
+        return typeof value == 'boolean';
+    }
+
+
+    function trim(value) {
+        return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value;
+    }
+
+    /**
+     * @ngdoc function
+     * @name angular.isElement
+     * @function
+     *
+     * @description
+     * Determines if a reference is a DOM element (or wrapped jQuery element).
+     *
+     * @param {*} value Reference to check.
+     * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
+     */
+    function isElement(node) {
+        return node &&
+            (node.nodeName  // we are a direct element
+                || (node.bind && node.find));  // we have a bind and find method part of jQuery API
+    }
+
+    /**
+     * @param str 'key1,key2,...'
+     * @returns {object} in the form of {key1:true, key2:true, ...}
+     */
+    function makeMap(str) {
+        var obj = {}, items = str.split(","), i;
+        for (i = 0; i < items.length; i++)
+            obj[ items[i] ] = true;
+        return obj;
+    }
+
+
+    if (msie < 9) {
+        nodeName_ = function (element) {
+            element = element.nodeName ? element : element[0];
+            return (element.scopeName && element.scopeName != 'HTML')
+                ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
+        };
+    } else {
+        nodeName_ = function (element) {
+            return element.nodeName ? element.nodeName : element[0].nodeName;
+        };
+    }
+
+
+    function map(obj, iterator, context) {
+        var results = [];
+        forEach(obj, function (value, index, list) {
+            results.push(iterator.call(context, value, index, list));
+        });
+        return results;
+    }
+
+
+    /**
+     * @description
+     * Determines the number of elements in an array, the number of properties an object has, or
+     * the length of a string.
+     *
+     * Note: This function is used to augment the Object type in Angular expressions. See
+     * {@link angular.Object} for more information about Angular arrays.
+     *
+     * @param {Object|Array|string} obj Object, array, or string to inspect.
+     * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
+     * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
+     */
+    function size(obj, ownPropsOnly) {
+        var size = 0, key;
+
+        if (isArray(obj) || isString(obj)) {
+            return obj.length;
+        } else if (isObject(obj)) {
+            for (key in obj)
+                if (!ownPropsOnly || obj.hasOwnProperty(key))
+                    size++;
+        }
+
+        return size;
+    }
+
+
+    function includes(array, obj) {
+        return indexOf(array, obj) != -1;
+    }
+
+    function indexOf(array, obj) {
+        if (array.indexOf) return array.indexOf(obj);
+
+        for (var i = 0; i < array.length; i++) {
+            if (obj === array[i]) return i;
+        }
+        return -1;
+    }
+
+    function arrayRemove(array, value) {
+        var index = indexOf(array, value);
+        if (index >= 0)
+            array.splice(index, 1);
+        return value;
+    }
+
+    function isLeafNode(node) {
+        if (node) {
+            switch (node.nodeName) {
+                case "OPTION":
+                case "PRE":
+                case "TITLE":
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @ngdoc function
+     * @name angular.copy
+     * @function
+     *
+     * @description
+     * Creates a deep copy of `source`, which should be an object or an array.
+     *
+     * * If no destination is supplied, a copy of the object or array is created.
+     * * If a destination is provided, all of its elements (for array) or properties (for objects)
+     *   are deleted and then all elements/properties from the source are copied to it.
+     * * If  `source` is not an object or array, `source` is returned.
+     *
+     * Note: this function is used to augment the Object type in Angular expressions. See
+     * {@link ng.$filter} for more information about Angular arrays.
+     *
+     * @param {*} source The source that will be used to make a copy.
+     *                   Can be any type, including primitives, `null`, and `undefined`.
+     * @param {(Object|Array)=} destination Destination into which the source is copied. If
+     *     provided, must be of the same type as `source`.
+     * @returns {*} The copy or updated `destination`, if `destination` was specified.
+     */
+    function copy(source, destination) {
+        if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope");
+        if (!destination) {
+            destination = source;
+            if (source) {
+                if (isArray(source)) {
+                    destination = copy(source, []);
+                } else if (isDate(source)) {
+                    destination = new Date(source.getTime());
+                } else if (isObject(source)) {
+                    destination = copy(source, {});
+                }
+            }
+        } else {
+            if (source === destination) throw Error("Can't copy equivalent objects or arrays");
+            if (isArray(source)) {
+                destination.length = 0;
+                for (var i = 0; i < source.length; i++) {
+                    destination.push(copy(source[i]));
+                }
+            } else {
+                var h = destination.$$hashKey;
+                forEach(destination, function (value, key) {
+                    delete destination[key];
+                });
+                for (var key in source) {
+                    destination[key] = copy(source[key]);
+                }
+                setHashKey(destination, h);
+            }
+        }
+        return destination;
+    }
+
+    /**
+     * Create a shallow copy of an object
+     */
+    function shallowCopy(src, dst) {
+        dst = dst || {};
+
+        for (var key in src) {
+            if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
+                dst[key] = src[key];
+            }
+        }
+
+        return dst;
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.equals
+     * @function
+     *
+     * @description
+     * Determines if two objects or two values are equivalent. Supports value types, arrays and
+     * objects.
+     *
+     * Two objects or values are considered equivalent if at least one of the following is true:
+     *
+     * * Both objects or values pass `===` comparison.
+     * * Both objects or values are of the same type and all of their properties pass `===` comparison.
+     * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)
+     *
+     * During a property comparision, properties of `function` type and properties with names
+     * that begin with `$` are ignored.
+     *
+     * Scope and DOMWindow objects are being compared only by identify (`===`).
+     *
+     * @param {*} o1 Object or value to compare.
+     * @param {*} o2 Object or value to compare.
+     * @returns {boolean} True if arguments are equal.
+     */
+    function equals(o1, o2) {
+        if (o1 === o2) return true;
+        if (o1 === null || o2 === null) return false;
+        if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
+        var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
+        if (t1 == t2) {
+            if (t1 == 'object') {
+                if (isArray(o1)) {
+                    if ((length = o1.length) == o2.length) {
+                        for (key = 0; key < length; key++) {
+                            if (!equals(o1[key], o2[key])) return false;
+                        }
+                        return true;
+                    }
+                } else if (isDate(o1)) {
+                    return isDate(o2) && o1.getTime() == o2.getTime();
+                } else {
+                    if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
+                    keySet = {};
+                    for (key in o1) {
+                        if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+                        if (!equals(o1[key], o2[key])) return false;
+                        keySet[key] = true;
+                    }
+                    for (key in o2) {
+                        if (!keySet[key] &&
+                            key.charAt(0) !== '$' &&
+                            o2[key] !== undefined && !isFunction(o2[key])) return false;
+                    }
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+
+    function concat(array1, array2, index) {
+        return array1.concat(slice.call(array2, index));
+    }
+
+    function sliceArgs(args, startIndex) {
+        return slice.call(args, startIndex || 0);
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.bind
+     * @function
+     *
+     * @description
+     * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
+     * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
+     * known as [function currying](http://en.wikipedia.org/wiki/Currying).
+     *
+     * @param {Object} self Context which `fn` should be evaluated in.
+     * @param {function()} fn Function to be bound.
+     * @param {...*} args Optional arguments to be prebound to the `fn` function call.
+     * @returns {function()} Function that wraps the `fn` with all the specified bindings.
+     */
+    function bind(self, fn) {
+        var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
+        if (isFunction(fn) && !(fn instanceof RegExp)) {
+            return curryArgs.length
+                ? function () {
+                return arguments.length
+                    ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
+                    : fn.apply(self, curryArgs);
+            }
+                : function () {
+                return arguments.length
+                    ? fn.apply(self, arguments)
+                    : fn.call(self);
+            };
+        } else {
+            // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
+            return fn;
+        }
+    }
+
+
+    function toJsonReplacer(key, value) {
+        var val = value;
+
+        if (/^\$+/.test(key)) {
+            val = undefined;
+        } else if (isWindow(value)) {
+            val = '$WINDOW';
+        } else if (value && document === value) {
+            val = '$DOCUMENT';
+        } else if (isScope(value)) {
+            val = '$SCOPE';
+        }
+
+        return val;
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.toJson
+     * @function
+     *
+     * @description
+     * Serializes input into a JSON-formatted string.
+     *
+     * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
+     * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
+     * @returns {string} Jsonified string representing `obj`.
+     */
+    function toJson(obj, pretty) {
+        return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
+    }
+
+
+    /**
+     * @ngdoc function
+     * @name angular.fromJson
+     * @function
+     *
+     * @description
+     * Deserializes a JSON string.
+     *
+     * @param {string} json JSON string to deserialize.
+     * @returns {Object|Array|Date|string|number} Deserialized thingy.
+     */
+    function fromJson(json) {
+        return isString(json)
+            ? JSON.parse(json)
+            : json;
+    }
+
+
+    function toBoolean(value) {
+        if (value && value.length !== 0) {
+            var v = lowercase("" + value);
+            value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
+        } else {
+            value = false;
+        }
+        return value;
+    }
+
+    /**
+     * @returns {string} Returns the string representation of the element.
+     */
+    function startingTag(element) {
+        element = jqLite(element).clone();
+        try {
+            // turns out IE does not let you set .html() on elements which
+            // are not allowed to have children. So we just ignore it.
+            element.html('');
+        } catch (e) {
+        }
+        // As Per DOM Standards
+        var TEXT_NODE = 3;
+        var elemHtml = jqLite('<div>').append(element).html();
+        try {
+            return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
+                elemHtml.
+                    match(/^(<[^>]+>)/)[1].
+                    replace(/^<([\w\-]+)/, function (match, nodeName) {
+                        return '<' + lowercase(nodeName);
+                    });
+        } catch (e) {
+            return lowercase(elemHtml);
+        }
+
+    }
+
+
+/////////////////////////////////////////////////
+
+    /**
+     * Parses an escaped url query string into key-value pairs.
+     * @returns Object.<(string|boolean)>
+     */
+    function parseKeyValue(/**string*/keyValue) {
+        var obj = {}, key_value, key;
+        forEach((keyValue || "").split('&'), function (keyValue) {
+            if (keyValue) {
+                key_value = keyValue.split('=');
+                key = decodeURIComponent(key_value[0]);
+                obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;
+            }
+        });
+        return obj;
+    }
+
+    function toKeyValue(obj) {
+        var parts = [];
+        forEach(obj, function (value, key) {
+            parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));
+        });
+        return parts.length ? parts.join('&') : '';
+    }
+
+
+    /**
+     * We need our custom method because encodeURIComponent is too agressive and doesn't follow
+     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+     * segments:
+     *    segment       = *pchar
+     *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+     *    pct-encoded   = "%" HEXDIG HEXDIG
+     *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+     *                     / "*" / "+" / "," / ";" / "="
+     */
+    function encodeUriSegment(val) {
+        return encodeUriQuery(val, true).
+            replace(/%26/gi, '&').
+            replace(/%3D/gi, '=').
+            replace(/%2B/gi, '+');
+    }
+
+
+    /**
+     * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
+     * encoded per http://tools.ietf.org/html/rfc3986:
+     *    query       = *( pchar / "/" / "?" )
+     *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+     *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     *    pct-encoded   = "%" HEXDIG HEXDIG
+     *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+     *                     / "*" / "+" / "," / ";" / "="
+     */
+    function encodeUriQuery(val, pctEncodeSpaces) {
+        return encodeURIComponent(val).
+            replace(/%40/gi, '@').
+            replace(/%3A/gi, ':').
+            replace(/%24/g, '$').
+            replace(/%2C/gi, ',').
+            replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
+    }
+
+
+    /**
+     * @ngdoc directive
+     * @name ng.directive:ngApp
+     *
+     * @element ANY
+     * @param {angular.Module} ngApp an optional application
+     *   {@link angular.module module} name to load.
+     *
+     * @description
+     *
+     * Use this directive to auto-bootstrap an application. Only
+     * one directive can be used per HTML document. The directive
+     * designates the root of the application and is typically placed
+     * at the root of the page.
+     *
+     * In the example below if the `ngApp` directive would not be placed
+     * on the `html` element then the document would not be compiled
+     * and the `{{ 1+2 }}` would not be resolved to `3`.
+     *
+     * `ngApp` is the easiest way to bootstrap an application.
+     *
+     <doc:example>
+     <doc:source>
+     I can add: 1 + 2 =  {{ 1+2 }}
+     </doc:source>
+     </doc:example>
+     *
+     */
+    function angularInit(element, bootstrap) {
+        var elements = [element],
+            appElement,
+            module,
+            names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
+            NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
+
+        function append(element) {
+            element && elements.push(element);
+        }
+
+        forEach(names, function (name) {
+            names[name] = true;
+            append(document.getElementById(name));
+            name = name.replace(':', '\\:');
+            if (element.querySelectorAll) {
+                forEach(element.querySelectorAll('.' + name), append);
+                forEach(element.querySelectorAll('.' + name + '\\:'), append);
+                forEach(element.querySelectorAll('[' + name + ']'), append);
+            }
+        });
+
+        forEach(elements, function (element) {
+            if (!appElement) {
+                var className = ' ' + element.className + ' ';
+                var match = NG_APP_CLASS_REGEXP.exec(className);
+                if (match) {
+                    appElement = element;
+                    module = (match[2] || '').replace(/\s+/g, ',');
+                } else {
+                    forEach(element.attributes, function (attr) {
+                        if (!appElement && names[attr.name]) {
+                            appElement = element;
+                            module = attr.value;
+                        }
+                    });
+                }
+            }
+        });
+        if (appElement) {
+            bootstrap(appElement, module ? [module] : []);
+        }
+    }
+
+    /**
+     * @ngdoc function
+     * @name angular.bootstrap
+     * @description
+     * Use this function to manually start up angular application.
+     *
+     * See: {@link guide/bootstrap Bootstrap}
+     *
+     * @param {Element} element DOM element which is the root of angular application.
+     * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}
+     * @returns {AUTO.$injector} Returns the newly created injector for this app.
+     */
+    function bootstrap(element, modules) {
+        var resumeBootstrapInternal = function () {
+            element = jqLite(element);
+            modules = modules || [];
+            modules.unshift(['$provide', function ($provide) {
+                $provide.value('$rootElement', element);
+            }]);
+            modules.unshift('ng');
+            var injector = createInjector(modules);
+            injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
+                function (scope, element, compile, injector) {
+                    scope.$apply(function () {
+                        element.data('$injector', injector);
+                        compile(element)(scope);
+                    });
+                }]
+            );
+            return injector;
+        };
+
+        var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
+
+        if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
+            return resumeBootstrapInternal();
+        }
+
+        window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
+        angular.resumeBootstrap = function (extraModules) {
+            forEach(extraModules, function (module) {
+                modules.push(module);
+            });
+            resumeBootstrapInternal();
+        };
+    }
+
+    var SNAKE_CASE_REGEXP = /[A-Z]/g;
+
+    function snake_case(name, separator) {
+        separator = separator || '_';
+        return name.replace(SNAKE_CASE_REGEXP, function (letter, pos) {
+            return (pos ? separator : '') + letter.toLowerCase();
+        });
+    }
+
+    function bindJQuery() {
+        // bind to jQuery if present;
+        jQuery = window.jQuery;
+        // reset to jQuery or default to us.
+        if (jQuery) {
+            jqLite = jQuery;
+            extend(jQuery.fn, {
+                scope: JQLitePrototype.scope,
+                controller: JQLitePrototype.controller,
+                injector: JQLitePrototype.injector,
+                inheritedData: JQLitePrototype.inheritedData
+            });
+            JQLitePatchJQueryRemove('remove', true);
+            JQLitePatchJQueryRemove('empty');
+            JQLitePatchJQueryRemove('html');
+        } else {
+            jqLite = JQLite;
+        }
+        angular.element = jqLite;
+    }
+
+    /**
+     * throw error if the argument is falsy.
+     */
+    function assertArg(arg, name, reason) {
+        if (!arg) {
+            throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required"));
+        }
+        return arg;
+    }
+
+    function assertArgFn(arg, name, acceptArrayAnnotation) {
+        if (acceptArrayAnnotation && isArray(arg)) {
+            arg = arg[arg.length - 1];
+        }
+
+        assertArg(isFunction(arg), name, 'not a function, got ' +
+            (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
+        return arg;
+    }
+
+    /**
+     * @ngdoc interface
+     * @name angular.Module
+     * @description
+     *
+     * Interface for configuring angular {@link angular.module modules}.
+     */
+
+    function setupModuleLoader(window) {
+
+        function ensure(obj, name, factory) {
+            return obj[name] || (obj[name] = factory());
+        }
+
+        return ensure(ensure(window, 'angular', Object), 'module', function () {
+            /** @type {Object.<string, angular.Module>} */
+            var modules = {};
+
+            /**
+             * @ngdoc function
+             * @name angular.module
+             * @description
+             *
+             * The `angular.module` is a global place for creating and registering Angular modules. All
+             * modules (angular core or 3rd party) that should be available to an application must be
+             * registered using this mechanism.
+             *
+             *
+             * # Module
+             *
+             * A module is a collocation of services, directives, filters, and configuration information. Module
+             * is used to configure the {@link AUTO.$injector $injector}.
+             *
+             * <pre>
+             * // Create a new module
+             * var myModule = angular.module('myModule', []);
+             *
+             * // register a new service
+             * myModule.value('appName', 'MyCoolApp');
+             *
+             * // configure existing services inside initialization blocks.
+             * myModule.config(function($locationProvider) {
+     *   // Configure existing providers
+     *   $locationProvider.hashPrefix('!');
+     * });
+             * </pre>
+             *
+             * Then you can create an injector and load your modules like this:
+             *
+             * <pre>
+             * var injector = angular.injector(['ng', 'MyModule'])
+             * </pre>
+             *
+             * However it's more likely that you'll just use
+             * {@link ng.directive:ngApp ngApp} or
+             * {@link angular.bootstrap} to simplify this process for you.
+             *
+             * @param {!string} name The name of the module to create or retrieve.
+             * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
+             *        the module is being retrieved for further configuration.
+             * @param {Function} configFn Optional configuration function for the module. Same as
+             *        {@link angular.Module#config Module#config()}.
+             * @returns {module} new module with the {@link angular.Module} api.
+             */
+            return function module(name, requires, configFn) {
+                if (requires && modules.hasOwnProperty(name)) {
+                    modules[name] = null;
+                }
+                return ensure(modules, name, function () {
+                    if (!requires) {
+                        throw Error('No module: ' + name);
+                    }
+
+                    /** @type {!Array.<Array.<*>>} */
+                    var invokeQueue = [];
+
+                    /** @type {!Array.<Function>} */
+                    var runBlocks = [];
+
+                    var config = invokeLater('$injector', 'invoke');
+
+                    /** @type {angular.Module} */
+                    var moduleInstance = {
+                        // Private state
+                        _invokeQueue: invokeQueue,
+                        _runBlocks: runBlocks,
+
+                        /**
+                         * @ngdoc property
+                         * @name angular.Module#requires
+                         * @propertyOf angular.Module
+                         * @returns {Array.<string>} List of module names which must be loaded before this module.
+                         * @description
+                         * Holds the list of modules which the injector will load before the current module is loaded.
+                         */
+                        requires: requires,
+
+                        /**
+                         * @ngdoc property
+                         * @name angular.Module#name
+                         * @propertyOf angular.Module
+                         * @returns {string} Name of the module.
+                         * @description
+                         */
+                        name: name,
+
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#provider
+                         * @methodOf angular.Module
+                         * @param {string} name service name
+                         * @param {Function} providerType Construction function for creating new instance of the service.
+                         * @description
+                         * See {@link AUTO.$provide#provider $provide.provider()}.
+                         */
+                        provider: invokeLater('$provide', 'provider'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#factory
+                         * @methodOf angular.Module
+                         * @param {string} name service name
+                         * @param {Function} providerFunction Function for creating new instance of the service.
+                         * @description
+                         * See {@link AUTO.$provide#factory $provide.factory()}.
+                         */
+                        factory: invokeLater('$provide', 'factory'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#service
+                         * @methodOf angular.Module
+                         * @param {string} name service name
+                         * @param {Function} constructor A constructor function that will be instantiated.
+                         * @description
+                         * See {@link AUTO.$provide#service $provide.service()}.
+                         */
+                        service: invokeLater('$provide', 'service'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#value
+                         * @methodOf angular.Module
+                         * @param {string} name service name
+                         * @param {*} object Service instance object.
+                         * @description
+                         * See {@link AUTO.$provide#value $provide.value()}.
+                         */
+                        value: invokeLater('$provide', 'value'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#constant
+                         * @methodOf angular.Module
+                         * @param {string} name constant name
+                         * @param {*} object Constant value.
+                         * @description
+                         * Because the constant are fixed, they get applied before other provide methods.
+                         * See {@link AUTO.$provide#constant $provide.constant()}.
+                         */
+                        constant: invokeLater('$provide', 'constant', 'unshift'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#filter
+                         * @methodOf angular.Module
+                         * @param {string} name Filter name.
+                         * @param {Function} filterFactory Factory function for creating new instance of filter.
+                         * @description
+                         * See {@link ng.$filterProvider#register $filterProvider.register()}.
+                         */
+                        filter: invokeLater('$filterProvider', 'register'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#controller
+                         * @methodOf angular.Module
+                         * @param {string} name Controller name.
+                         * @param {Function} constructor Controller constructor function.
+                         * @description
+                         * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+                         */
+                        controller: invokeLater('$controllerProvider', 'register'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#directive
+                         * @methodOf angular.Module
+                         * @param {string} name directive name
+                         * @param {Function} directiveFactory Factory function for creating new instance of
+                         * directives.
+                         * @description
+                         * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+                         */
+                        directive: invokeLater('$compileProvider', 'directive'),
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#config
+                         * @methodOf angular.Module
+                         * @param {Function} configFn Execute this function on module load. Useful for service
+                         *    configuration.
+                         * @description
+                         * Use this method to register work which needs to be performed on module loading.
+                         */
+                        config: config,
+
+                        /**
+                         * @ngdoc method
+                         * @name angular.Module#run
+                         * @methodOf angular.Module
+                         * @param {Function} initializationFn Execute this function after injector creation.
+                         *    Useful for application initialization.
+                         * @description
+                         * Use this method to register work which should be performed when the injector is done
+                         * loading all modules.
+                         */
+                        run: function (block) {
+                            runBlocks.push(block);
+                            return this;
+                        }
+                    };
+
+                    if (configFn) {
+                        config(configFn);
+                    }
+
+                    return  moduleInstance;
+
+                    /**
+                     * @param {string} provider
+                     * @param {string} method
+                     * @param {String=} insertMethod
+                     * @returns {angular.Module}
+                     */
+                    function invokeLater(provider, method, insertMethod) {
+                        return function () {
+                            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
+                            return moduleInstance;
+                        }
+                    }
+                });
+            };
+        });
+
+    }
+
+    /**
+     * @ngdoc property
+     * @name angular.version
+     * @description
+     * An object that contains information about the current AngularJS version. This object has the
+     * following properties:
+     *
+     * - `full` – `{string}` – Full version string, such as "0.9.18".
+     * - `major` – `{number}` – Major version number, such as "0".
+     * - `minor` – `{number}` – Minor version number, such as "9".
+     * - `dot` – `{number}` – Dot version number, such as "18".
+     * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
+     */
+    var version = {
+        full: '1.0.7',    // all of these placeholder strings will be replaced by grunt's
+        major: 1,    // package task
+        minor: 0,
+        dot: 7,
+        codeName: 'monochromatic-rainbow'
+    };
+
+
+    function publishExternalAPI(angular) {
+        extend(angular, {
+            'bootstrap': bootstrap,
+            'copy': copy,
+            'extend': extend,
+            'equals': equals,
+            'element': jqLite,
+            'forEach': forEach,
+            'injector': createInjector,
+            'noop': noop,
+            'bind': bind,
+            'toJson': toJson,
+            'fromJson': fromJson,
+            'identity': identity,
+            'isUndefined': isUndefined,
+            'isDefined': isDefined,
+            'isString': isString,
+            'isFunction': isFunction,
+            'isObject': isObject,
+            'isNumber': isNumber,
+            'isElement': isElement,
+            'isArray': isArray,
+            'version': version,
+            'isDate': isDate,
+            'lowercase': lowercase,
+            'uppercase': uppercase,
+            'callbacks': {counter: 0}
+        });
+
+        angularModule = setupModuleLoader(window);
+        try {
+            angularModule('ngLocale');
+        } catch (e) {
+            angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
+        }
+
+        angularModule('ng', ['ngLocale'], ['$provide',
+            function ngModule($provide) {
+                $provide.provider('$compile', $CompileProvider).
+                    directive({
+                        a: htmlAnchorDirective,
+                        input: inputDirective,
+                        textarea: inputDirective,
+                        form: formDirective,
+                        script: scriptDirective,
+                        select: selectDirective,
+                        style: styleDirective,
+                        option: optionDirective,
+                        ngBind: ngBindDirective,
+                        ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,
+                        ngBindTemplate: ngBindTemplateDirective,
+                        ngClass: ngClassDirective,
+                        ngClassEven: ngClassEvenDirective,
+                        ngClassOdd: ngClassOddDirective,
+                        ngCsp: ngCspDirective,
+                        ngCloak: ngCloakDirective,
+                        ngController: ngControllerDirective,
+                        ngForm: ngFormDirective,
+                        ngHide: ngHideDirective,
+                        ngInclude: ngIncludeDirective,
+                        ngInit: ngInitDirective,
+                        ngNonBindable: ngNonBindableDirective,
+                        ngPluralize: ngPluralizeDirective,
+                        ngRepeat: ngRepeatDirective,
+                        ngShow: ngShowDirective,
+                        ngSubmit: ngSubmitDirective,
+                        ngStyle: ngStyleDirective,
+                        ngSwitch: ngSwitchDirective,
+                        ngSwitchWhen: ngSwitchWhenDirective,
+                        ngSwitchDefault: ngSwitchDefaultDirective,
+                        ngOptions: ngOptionsDirective,
+                        ngView: ngViewDirective,
+                        ngTransclude: ngTranscludeDirective,
+                        ngModel: ngModelDirective,
+                        ngList: ngListDirective,
+                        ngChange: ngChangeDirective,
+                        required: requiredDirective,
+                        ngRequired: requiredDirective,
+                        ngValue: ngValueDirective
+                    }).
+                    directive(ngAttributeAliasDirectives).
+                    directive(ngEventDirectives);
+                $provide.provider({
+                    $anchorScroll: $AnchorScrollProvider,
+                    $browser: $BrowserProvider,
+                    $cacheFactory: $CacheFactoryProvider,
+                    $controller: $ControllerProvider,
+                    $document: $DocumentProvider,
+                    $exceptionHandler: $ExceptionHandlerProvider,
+                    $filter: $FilterProvider,
+                    $interpolate: $InterpolateProvider,
+                    $http: $HttpProvider,
+                    $httpBackend: $HttpBackendProvider,
+                    $location: $LocationProvider,
+                    $log: $LogProvider,
+                    $parse: $ParseProvider,
+                    $route: $RouteProvider,
+                    $routeParams: $RouteParamsProvider,
+                    $rootScope: $RootScopeProvider,
+                    $q: $QProvider,
+                    $sniffer: $SnifferProvider,
+                    $templateCache: $TemplateCacheProvider,
+                    $timeout: $TimeoutProvider,
+                    $window: $WindowProvider
+                });
+            }
+        ]);
+    }
+
+//////////////////////////////////
+//JQLite
+//////////////////////////////////
+
+    /**
+     * @ngdoc function
+     * @name angular.element
+     * @function
+     *
+     * @description
+     * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
+     * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if
+     * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite
+     * implementation (commonly referred to as jqLite).
+     *
+     * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`
+     * event fired.
+     *
+     * jqLite is a tiny, API-compatible subset of jQuery that allows
+     * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality
+     * within a very small footprint, so only a subset of the jQuery API - methods, arguments and
+     * invocation styles - are supported.
+     *
+     * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never
+     * raw DOM references.
+     *
+     * ## Angular's jQuery lite provides the following methods:
+     *
+     * - [addClass()](http://api.jquery.com/addClass/)
+     * - [after()](http://api.jquery.com/after/)
+     * - [append()](http://api.jquery.com/append/)
+     * - [attr()](http://api.jquery.com/attr/)
+     * - [bind()](http://api.jquery.com/bind/) - Does not support namespaces
+     * - [children()](http://api.jquery.com/children/) - Does not support selectors
+     * - [clone()](http://api.jquery.com/clone/)
+     * - [contents()](http://api.jquery.com/contents/)
+     * - [css()](http://api.jquery.com/css/)
+     * - [data()](http://api.jquery.com/data/)
+     * - [eq()](http://api.jquery.com/eq/)
+     * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name
+     * - [hasClass()](http://api.jquery.com/hasClass/)
+     * - [html()](http://api.jquery.com/html/)
+     * - [next()](http://api.jquery.com/next/) - Does not support selectors
+     * - [parent()](http://api.jquery.com/parent/) - Does not support selectors
+     * - [prepend()](http://api.jquery.com/prepend/)
+     * - [prop()](http://api.jquery.com/prop/)
+     * - [ready()](http://api.jquery.com/ready/)
+     * - [remove()](http://api.jquery.com/remove/)
+     * - [removeAttr()](http://api.jquery.com/removeAttr/)
+     * - [removeClass()](http://api.jquery.com/removeClass/)
+     * - [removeData()](http://api.jquery.com/removeData/)
+     * - [replaceWith()](http://api.jquery.com/replaceWith/)
+     * - [text()](http://api.jquery.com/text/)
+     * - [toggleClass()](http://api.jquery.com/toggleClass/)
+     * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
+     * - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces
+     * - [val()](http://api.jquery.com/val/)
+     * - [wrap()](http://api.jquery.com/wrap/)
+     *
+     * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
+     *
+     * - `controller(name)` - retrieves the controller of the current element or its parent. By default
+     *   retrieves controller associated with the `ngController` directive. If `name` is provided as
+     *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
+     *   `'ngModel'`).
+     * - `injector()` - retrieves the injector of the current element or its parent.
+     * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current
+     *   element or its parent.
+     * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
+     *   parent element is reached.
+     *
+     * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
+     * @returns {Object} jQuery object.
+     */
+
+    var jqCache = JQLite.cache = {},
+        jqName = JQLite.expando = 'ng-' + new Date().getTime(),
+        jqId = 1,
+        addEventListenerFn = (window.document.addEventListener
+            ? function (element, type, fn) {
+            element.addEventListener(type, fn, false);
+        }
+            : function (element, type, fn) {
+            element.attachEvent('on' + type, fn);
+        }),
+        removeEventListenerFn = (window.document.removeEventListener
+            ? function (element, type, fn) {
+            element.removeEventListener(type, fn, false);
+        }
+            : function (element, type, fn) {
+            element.detachEvent('on' + type, fn);
+        });
+
+    function jqNextId() {
+        return ++jqId;
+    }
+
+
+    var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
+    var MOZ_HACK_REGEXP = /^moz([A-Z])/;
+
+    /**
+     * Converts snake_case to camelCase.
+     * Also there is special case for Moz prefix starting with upper case letter.
+     * @param name Name to normalize
+     */
+    function camelCase(name) {
+        return name.
+            replace(SPECIAL_CHARS_REGEXP,function (_, separator, letter, offset) {
+                return offset ? letter.toUpperCase() : letter;
+            }).
+            replace(MOZ_HACK_REGEXP, 'Moz$1');
+    }
+
+/////////////////////////////////////////////
+// jQuery mutation patch
+//
+//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
+// $destroy event on all DOM nodes being removed.
+//
+/////////////////////////////////////////////
+
+    function JQLitePatchJQueryRemove(name, dispatchThis) {
+        var originalJqFn = jQuery.fn[name];
+        originalJqFn = originalJqFn.$original || originalJqFn;
+        removePatch.$original = originalJqFn;
+        jQuery.fn[name] = removePatch;
+
+        function removePatch() {
+            var list = [this],
+                fireEvent = dispatchThis,
+                set, setIndex, setLength,
+                element, childIndex, childLength, children,
+                fns, events;
+
+            while (list.length) {
+                set = list.shift();
+                for (setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
+                    element = jqLite(set[setIndex]);
+                    if (fireEvent) {
+                        element.triggerHandler('$destroy');
+                    } else {
+                        fireEvent = !fireEvent;
+                    }
+                    for (childIndex = 0, childLength = (children = element.children()).length;
+                         childIndex < childLength;
+                         childIndex++) {
+                        list.push(jQuery(children[childIndex]));
+                    }
+                }
+            }
+            return originalJqFn.apply(this, arguments);
+        }
+    }
+
+/////////////////////////////////////////////
+    function JQLite(element) {
+        if (element instanceof JQLite) {
+            return element;
+        }
+        if (!(this instanceof JQLite)) {
+            if (isString(element) && element.charAt(0) != '<') {
+                throw Error('selectors not implemented');
+            }
+            return new JQLite(element);
+        }
+
+        if (isString(element)) {
+            var div = document.createElement('div');
+            // Read about the NoScope elements here:
+            // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
+            div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!
+            div.removeChild(div.firstChild); // remove the superfluous div
+            JQLiteAddNodes(this, div.childNodes);
+            this.remove(); // detach the elements from the temporary DOM div.
+        } else {
+            JQLiteAddNodes(this, element);
+        }
+    }
+
+    function JQLiteClone(element) {
+        return element.cloneNode(true);
+    }
+
+    function JQLiteDealoc(element) {
+        JQLiteRemoveData(element);
+        for (var i = 0, children = element.childNodes || []; i < children.length; i++) {
+            JQLiteDealoc(children[i]);
+        }
+    }
+
+    function JQLiteUnbind(element, type, fn) {
+        var events = JQLiteExpandoStore(element, 'events'),
+            handle = JQLiteExpandoStore(element, 'handle');
+
+        if (!handle) return; //no listeners registered
+
+        if (isUndefined(type)) {
+            forEach(events, function (eventHandler, type) {
+                removeEventListenerFn(element, type, eventHandler);
+                delete events[type];
+            });
+        } else {
+            if (isUndefined(fn)) {
+                removeEventListenerFn(element, type, events[type]);
+                delete events[type];
+            } else {
+                arrayRemove(events[type], fn);
+            }
+        }
+    }
+
+    function JQLiteRemoveData(element) {
+        var expandoId = element[jqName],
+            expandoStore = jqCache[expandoId];
+
+        if (expandoStore) {
+            if (expandoStore.handle) {
+                expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
+                JQLiteUnbind(element);
+            }
+            delete jqCache[expandoId];
+            element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
+        }
+    }
+
+    function JQLiteExpandoStore(element, key, value) {
+        var expandoId = element[jqName],
+            expandoStore = jqCache[expandoId || -1];
+
+        if (isDefined(value)) {
+            if (!expandoStore) {
+                element[jqName] = expandoId = jqNextId();
+                expandoStore = jqCache[expandoId] = {};
+            }
+            expandoStore[key] = value;
+        } else {
+            return expandoStore && expandoStore[key];
+        }
+    }
+
+    function JQLiteData(element, key, value) {
+        var data = JQLiteExpandoStore(element, 'data'),
+            isSetter = isDefined(value),
+            keyDefined = !isSetter && isDefined(key),
+            isSimpleGetter = keyDefined && !isObject(key);
+
+        if (!data && !isSimpleGetter) {
+            JQLiteExpandoStore(element, 'data', data = {});
+        }
+
+        if (isSetter) {
+            data[key] = value;
+        } else {
+            if (keyDefined) {
+                if (isSimpleGetter) {
+                    // don't create data in this case.
+                    return data && data[key];
+                } else {
+                    extend(data, key);
+                }
+            } else {
+                return data;
+            }
+        }
+    }
+
+    function JQLiteHasClass(element, selector) {
+        return ((" " + element.className + " ").replace(/[\n\t]/g, " ").
+            indexOf(" " + selector + " ") > -1);
+    }
+
+    function JQLiteRemoveClass(element, cssClasses) {
+        if (cssClasses) {
+            forEach(cssClasses.split(' '), function (cssClass) {
+                element.className = trim(
+                    (" " + element.className + " ")
+                        .replace(/[\n\t]/g, " ")
+                        .replace(" " + trim(cssClass) + " ", " ")
+                );
+            });
+        }
+    }
+
+    function JQLiteAddClass(element, cssClasses) {
+        if (cssClasses) {
+            forEach(cssClasses.split(' '), function (cssClass) {
+                if (!JQLiteHasClass(element, cssClass)) {
+                    element.className = trim(element.className + ' ' + trim(cssClass));
+                }
+            });
+        }
+    }
+
+    function JQLiteAddNodes(root, elements) {
+        if (elements) {
+            elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
+                ? elements
+                : [ elements ];
+            for (var i = 0; i < elements.length; i++) {
+                root.push(elements[i]);
+            }
+        }
+    }
+
+    function JQLiteController(element, name) {
+        return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
+    }
+
+    function JQLiteInheritedData(element, name, value) {
+        element = jqLite(element);
+
+        // if element is the document object work with the html element instead
+        // this makes $(document).scope() possible
+        if (element[0].nodeType == 9) {
+            element = element.find('html');
+        }
+
+        while (element.length) {
+            if (value = element.data(name)) return value;
+            element = element.parent();
+        }
+    }
+
+//////////////////////////////////////////
+// Functions which are declared directly.
+//////////////////////////////////////////
+    var JQLitePrototype = JQLite.prototype = {
+        ready: function (fn) {
+            var fired = false;
+
+            function trigger() {
+                if (fired) return;
+                fired = true;
+                fn();
+            }
+
+            this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9
+            // we can not use jqLite since we are not done loading and jQuery could be loaded later.
+            JQLite(window).bind('load', trigger); // fallback to window.onload for others
+        },
+        toString: function () {
+            var value = [];
+            forEach(this, function (e) {
+                value.push('' + e);
+            });
+            return '[' + value.join(', ') + ']';
+        },
+
+        eq: function (index) {
+            return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
+        },
+
+        length: 0,
+        push: push,
+        sort: [].sort,
+        splice: [].splice
+    };
+
+//////////////////////////////////////////
+// Functions iterating getter/setters.
+// these functions return self on setter and
+// value on get.
+//////////////////////////////////////////
+    var BOOLEAN_ATTR = {};
+    forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function (value) {
+        BOOLEAN_ATTR[lowercase(value)] = value;
+    });
+    var BOOLEAN_ELEMENTS = {};
+    forEach('input,select,option,textarea,button,form'.split(','), function (value) {
+        BOOLEAN_ELEMENTS[uppercase(value)] = true;
+    });
+
+    function getBooleanAttrName(element, name) {
+        // check dom last since we will most likely fail on name
+        var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
+
+        // booleanAttr is here twice to minimize DOM access
+        return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
+    }
+
+    forEach({
+        data: JQLiteData,
+        inheritedData: JQLiteInheritedData,
+
+        scope: function (element) {
+            return JQLiteInheritedData(element, '$scope');
+        },
+
+        controller: JQLiteController,
+
+        injector: function (element) {
+            return JQLiteInheritedData(element, '$injector');
+        },
+
+        removeAttr: function (element, name) {
+            element.removeAttribute(name);
+        },
+
+        hasClass: JQLiteHasClass,
+
+        css: function (element, name, value) {
+            name = camelCase(name);
+
+            if (isDefined(value)) {
+                element.style[name] = value;
+            } else {
+                var val;
+
+                if (msie <= 8) {
+                    // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
+                    val = element.currentStyle && element.currentStyle[name];
+                    if (val === '') val = 'auto';
+                }
+
+                val = val || element.style[name];
+
+                if (msie <= 8) {
+                    // jquery weirdness :-/
+                    val = (val === '') ? undefined : val;
+                }
+
+                return  val;
+            }
+        },
+
+        attr: function (element, name, value) {
+            var lowercasedName = lowercase(name);
+            if (BOOLEAN_ATTR[lowercasedName]) {
+                if (isDefined(value)) {
+                    if (!!value) {
+                        element[name] = true;
+                        element.setAttribute(name, lowercasedName);
+                    } else {
+                        element[name] = false;
+                        element.removeAttribute(lowercasedName);
+                    }
+                } else {
+                    return (element[name] ||
+                        (element.attributes.getNamedItem(name) || noop).specified)
+                        ? lowercasedName
+                        : undefined;
+                }
+            } else if (isDefined(value)) {
+                element.setAttribute(name, value);
+            } else if (element.getAttribute) {
+                // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
+                // some elements (e.g. Document) don't have get attribute, so return undefined
+                var ret = element.getAttribute(name, 2);
+                // normalize non-existing attributes to undefined (as jQuery)
+                return ret === null ? undefined : ret;
+            }
+        },
+
+        prop: function (element, name, value) {
+            if (isDefined(value)) {
+                element[name] = value;
+            } else {
+                return element[name];
+            }
+        },
+
+        text: extend((msie < 9)
+            ? function (element, value) {
+            if (element.nodeType == 1 /** Element */) {
+                if (isUndefined(value))
+                    return element.innerText;
+                element.innerText = value;
+            } else {
+                if (isUndefined(value))
+                    return element.nodeValue;
+                element.nodeValue = value;
+            }
+        }
+            : function (element, value) {
+            if (isUndefined(value)) {
+                return element.textContent;
+            }
+            element.textContent = value;
+        }, {$dv: ''}),
+
+        val: function (element, value) {
+            if (isUndefined(value)) {
+                return element.value;
+            }
+            element.value = value;
+        },
+
+        html: function (element, value) {
+            if (isUndefined(value)) {
+                return element.innerHTML;
+            }
+            for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
+                JQLiteDealoc(childNodes[i]);
+            }
+            element.innerHTML = value;
+        }
+    }, function (fn, name) {
+        /**
+         * Properties: writes return selection, reads return first value
+         */
+        JQLite.prototype[name] = function (arg1, arg2) {
+            var i, key;
+
+            // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
+            // in a way that survives minification.
+            if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {
+                if (isObject(arg1)) {
+
+                    // we are a write, but the object properties are the key/values
+                    for (i = 0; i < this.length; i++) {
+                        if (fn === JQLiteData) {
+                            // data() takes the whole object in jQuery
+                            fn(this[i], arg1);
+                        } else {
+                            for (key in arg1) {
+                                fn(this[i], key, arg1[key]);
+                            }
+                        }
+                    }
+                    // return self for chaining
+                    return this;
+                } else {
+                    // we are a read, so read the first child.
+                    if (this.length)
+                        return fn(this[0], arg1, arg2);
+                }
+            } else {
+                // we are a write, so apply to all children
+                for (i = 0; i < this.length; i++) {
+                    fn(this[i], arg1, arg2);
+                }
+                // return self for chaining
+                return this;
+            }
+            return fn.$dv;
+        };
+    });
+
+    function createEventHandler(element, events) {
+        var eventHandler = function (event, type) {
+            if (!event.preventDefault) {
+                event.preventDefault = function () {
+                    event.returnValue = false; //ie
+                };
+            }
+
+            if (!event.stopPropagation) {
+                event.stopPropagation = function () {
+                    event.cancelBubble = true; //ie
+                };
+            }
+
+            if (!event.target) {
+                event.target = event.srcElement || document;
+            }
+
+            if (isUndefined(event.defaultPrevented)) {
+                var prevent = event.preventDefault;
+                event.preventDefault = function () {
+                    event.defaultPrevented = true;
+                    prevent.call(event);
+                };
+                event.defaultPrevented = false;
+            }
+
+            event.isDefaultPrevented = function () {
+                return event.defaultPrevented;
+            };
+
+            forEach(events[type || event.type], function (fn) {
+                fn.call(element, event);
+            });
+
+            // Remove monkey-patched methods (IE),
+            // as they would cause memory leaks in IE8.
+            if (msie <= 8) {
+                // IE7/8 does not allow to delete property on native object
+                event.preventDefault = null;
+                event.stopPropagation = null;
+                event.isDefaultPrevented = null;
+            } else {
+                // It shouldn't affect normal browsers (native methods are defined on prototype).
+                delete event.preventDefault;
+                delete event.stopPropagation;
+                delete event.isDefaultPrevented;
+            }
+        };
+        eventHandler.elem = element;
+        return eventHandler;
+    }
+
+//////////////////////////////////////////
+// Functions iterating traversal.
+// These functions chain results into a single
+// selector.
+//////////////////////////////////////////
+    forEach({
+        removeData: JQLiteRemoveData,
+
+        dealoc: JQLiteDealoc,
+
+        bind: function bindFn(element, type, fn) {
+            var events = JQLiteExpandoStore(element, 'events'),
+                handle = JQLiteExpandoStore(element, 'handle');
+
+            if (!events) JQLiteExpandoStore(element, 'events', events = {});
+            if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
+
+            forEach(type.split(' '), function (type) {
+                var eventFns = events[type];
+
+                if (!eventFns) {
+                    if (type == 'mouseenter' || type == 'mouseleave') {
+                        var contains = document.body.contains || document.body.compareDocumentPosition ?
+                            function (a, b) {
+                                var adown = a.nodeType === 9 ? a.documentElement : a,
+                                    bup = b && b.parentNode;
+                                return a === bup || !!( bup && bup.nodeType === 1 && (
+                                    adown.contains ?
+                                        adown.contains(bup) :
+                                        a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16
+                                    ));
+                            } :
+                            function (a, b) {
+                                if (b) {
+                                    while ((b = b.parentNode)) {
+                                        if (b === a) {
+                                            return true;
+                                        }
+                                    }
+                                }
+                                return false;
+                            };
+
+                        events[type] = [];
+
+                        // Refer to jQuery's implementation of mouseenter & mouseleave
+                        // Read about mouseenter and mouseleave:
+                        // http://www.quirksmode.org/js/events_mouse.html#link8
+                        var eventmap = { mouseleave: "mouseout", mouseenter: "mouseover"}
+                        bindFn(element, eventmap[type], function (event) {
+                            var ret, target = this, related = event.relatedTarget;
+                            // For mousenter/leave call the handler if related is outside the target.
+                            // NB: No relatedTarget if the mouse left/entered the browser window
+                            if (!related || (related !== target && !contains(target, related))) {
+                                handle(event, type);
+                            }
+
+                        });
+
+                    } else {
+                        addEventListenerFn(element, type, handle);
+                        events[type] = [];
+                    }
+                    eventFns = events[type]
+                }
+                eventFns.push(fn);
+            });
+        },
+
+        unbind: JQLiteUnbind,
+
+        replaceWith: function (element, replaceNode) {
+            var index, parent = element.parentNode;
+            JQLiteDealoc(element);
+            forEach(new JQLite(replaceNode), function (node) {
+                if (index) {
+                    parent.insertBefore(node, index.nextSibling);
+                } else {
+                    parent.replaceChild(node, element);
+                }
+                index = node;
+            });
+        },
+
+        children: function (element) {
+            var children = [];
+            forEach(element.childNodes, function (element) {
+                if (element.nodeType === 1)
+                    children.push(element);
+            });
+            return children;
+        },
+
+        contents: function (element) {
+            return element.childNodes || [];
+        },
+
+        append: function (element, node) {
+            forEach(new JQLite(node), function (child) {
+                if (element.nodeType === 1)
+                    element.appendChild(child);
+            });
+        },
+
+        prepend: function (element, node) {
+            if (element.nodeType === 1) {
+                var index = element.firstChild;
+                forEach(new JQLite(node), function (child) {
+                    if (index) {
+                        element.insertBefore(child, index);
+                    } else {
+                        element.appendChild(child);
+                        index = child;
+                    }
+                });
+            }
+        },
+
+        wrap: function (element, wrapNode) {
+            wrapNode = jqLite(wrapNode)[0];
+            var parent = element.parentNode;
+            if (parent) {
+                parent.replaceChild(wrapNode, element);
+            }
+            wrapNode.appendChild(element);
+        },
+
+        remove: function (element) {
+            JQLiteDealoc(element);
+            var parent = element.parentNode;
+            if (parent) parent.removeChild(element);
+        },
+
+        after: function (element, newElement) {
+            var index = element, parent = element.parentNode;
+            forEach(new JQLite(newElement), function (node) {
+                parent.insertBefore(node, index.nextSibling);
+                index = node;
+            });
+        },
+
+        addClass: JQLiteAddClass,
+        removeClass: JQLiteRemoveClass,
+
+        toggleClass: function (element, selector, condition) {
+            if (isUndefined(condition)) {
+                condition = !JQLiteHasClass(element, selector);
+            }
+            (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);
+        },
+
+        parent: function (element) {
+            var parent = element.parentNode;
+            return parent && parent.nodeType !== 11 ? parent : null;
+        },
+
+        next: function (element) {
+            if (element.nextElementSibling) {
+                return element.nextElementSibling;
+            }
+
+            // IE8 doesn't have nextElementSibling
+            var elm = element.nextSibling;
+            while (elm != null && elm.nodeType !== 1) {
+                elm = elm.nextSibling;
+            }
+            return elm;
+        },
+
+        find: function (element, selector) {
+            return element.getElementsByTagName(selector);
+        },
+
+        clone: JQLiteClone,
+
+        triggerHandler: function (element, eventName) {
+            var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
+
+            forEach(eventFns, function (fn) {
+                fn.call(element, null);
+            });
+        }
+    }, function (fn, name) {
+        /**
+         * chaining functions
+         */
+        JQLite.prototype[name] = function (arg1, arg2) {
+            var value;
+            for (var i = 0; i < this.length; i++) {
+                if (value == undefined) {
+                    value = fn(this[i], arg1, arg2);
+                    if (value !== undefined) {
+                        // any function which returns a value needs to be wrapped
+                        value = jqLite(value);
+                    }
+                } else {
+                    JQLiteAddNodes(value, fn(this[i], arg1, arg2));
+                }
+            }
+            return value == undefined ? this : value;
+        };
+    });
+
+    /**
+     * Computes a hash of an 'obj'.
+     * Hash of a:
+     *  string is string
+     *  number is number as string
+     *  object is either result of calling $$hashKey function on the object or uniquely generated id,
+     *         that is also assigned to the $$hashKey property of the object.
+     *
+     * @param obj
+     * @returns {string} hash string such that the same input will have the same hash string.
+     *         The resulting string key is in 'type:hashKey' format.
+     */
+    function hashKey(obj) {
+        var objType = typeof obj,
+            key;
+
+        if (objType == 'object' && obj !== null) {
+            if (typeof (key = obj.$$hashKey) == 'function') {
+                // must invoke on object to keep the right this
+                key = obj.$$hashKey();
+            } else if (key === undefined) {
+                key = obj.$$hashKey = nextUid();
+            }
+        } else {
+            key = obj;
+        }
+
+        return objType + ':' + key;
+    }
+
+    /**
+     * HashMap which can use objects as keys
+     */
+    function HashMap(array) {
+        forEach(array, this.put, this);
+    }
+
+    HashMap.prototype = {
+        /**
+         * Store key value pair
+         * @param key key to store can be any type
+         * @param value value to store can be any type
+         */
+        put: function (key, value) {
+            this[hashKey(key)] = value;
+        },
+
+        /**
+         * @param key
+         * @returns the value for the key
+         */
+        get: function (key) {
+            return this[hashKey(key)];
+        },
+
+        /**
+         * Remove the key/value pair
+         * @param key
+         */
+        remove: function (key) {
+            var value = this[key = hashKey(key)];
+            delete this[key];
+            return value;
+        }
+    };
+
+    /**
+     * A map where multiple values can be added to the same key such that they form a queue.
+     * @returns {HashQueueMap}
+     */
+    function HashQueueMap() {
+    }
+
+    HashQueueMap.prototype = {
+        /**
+         * Same as array push, but using an array as the value for the hash
+         */
+        push: function (key, value) {
+            var array = this[key = hashKey(key)];
+            if (!array) {
+                this[key] = [value];
+            } else {
+                array.push(value);
+            }
+        },
+
+        /**
+         * Same as array shift, but using an array as the value for the hash
+         */
+        shift: function (key) {
+            var array = this[key = hashKey(key)];
+            if (array) {
+                if (array.length == 1) {
+                    delete this[key];
+                    return array[0];
+                } else {
+                    return array.shift();
+                }
+            }
+        },
+
+        /**
+         * return the first item without deleting it
+         */
+        peek: function (key) {
+            var array = this[hashKey(key)];
+            if (array) {
+                return array[0];
+            }
+        }
+    };
+
+    /**
+     * @ngdoc function
+     * @name angular.injector
+     * @function
+     *
+     * @description
+     * Creates an injector function that can be used for retrieving services as well as for
+     * dependency injection (see {@link guide/di dependency injection}).
+     *
+
+     * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
+     *        {@link angular.module}. The `ng` module must be explicitly added.
+     * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.
+     *
+     * @example
+     * Typical usage
+     * <pre>
+     *   // create an injector
+     *   var $injector = angular.injector(['ng']);
+     *
+     *   // use the injector to kick off your application
+     *   // use the type inference to auto inject arguments, or use implicit injection
+     *   $injector.invoke(function($rootScope, $compile, $document){
+ *     $compile($document)($rootScope);
+ *     $rootScope.$digest();
+ *   });
+     * </pre>
+     */
+
+
+    /**
+     * @ngdoc overview
+     * @name AUTO
+     * @description
+     *
+     * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
+     */
+
+    var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
+    var FN_ARG_SPLIT = /,/;
+    var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
+    var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
+
+    function annotate(fn) {
+        var $inject,
+            fnText,
+            argDecl,
+            last;
+
+        if (typeof fn == 'function') {
+            if (!($inject = fn.$inject)) {
+                $inject = [];
+                fnText = fn.toString().replace(STRIP_COMMENTS, '');
+                argDecl = fnText.match(FN_ARGS);
+                forEach(argDecl[1].split(FN_ARG_SPLIT), function (arg) {
+                    arg.replace(FN_ARG, function (all, underscore, name) {
+                        $inject.push(name);
+                    });
+                });
+                fn.$inject = $inject;
+            }
+        } else if (isArray(fn)) {
+            last = fn.length - 1;
+            assertArgFn(fn[last], 'fn');
+            $inject = fn.slice(0, last);
+        } else {
+            assertArgFn(fn, 'fn', true);
+        }
+        return $inject;
+    }
+
+///////////////////////////////////////
+
+    /**
+     * @ngdoc object
+     * @name AUTO.$injector
+     * @function
+     *
+     * @description
+     *
+     * `$injector` is used to retrieve object instances as defined by
+     * {@link AUTO.$provide provider}, instantiate types, invoke methods,
+     * and load modules.
+     *
+     * The following always holds true:
+     *
+     * <pre>
+     *   var $injector = angular.injector();
+     *   expect($injector.get('$injector')).toBe($injector);
+     *   expect($injector.invoke(function($injector){
+ *     return $injector;
+ *   }).toBe($injector);
+     * </pre>
+     *
+     * # Injection Function Annotation
+     *
+     * JavaScript does not have annotations, and annotations are needed for dependency injection. The
+     * following are all valid ways of annotating function with injection arguments and are equivalent.
+     *
+     * <pre>
+     *   // inferred (only works if code not minified/obfuscated)
+     *   $injector.invoke(function(serviceA){});
+     *
+     *   // annotated
+     *   function explicit(serviceA) {};
+     *   explicit.$inject = ['serviceA'];
+     *   $injector.invoke(explicit);
+     *
+     *   // inline
+     *   $injector.invoke(['serviceA', function(serviceA){}]);
+     * </pre>
+     *
+     * ## Inference
+     *
+     * In JavaScript calling `toString(

<TRUNCATED>