OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/eos/zephyr
[eos/zephyr.git] / front-end / dist / bundle.js
1 /******/ (function(modules) { // webpackBootstrap
2 /******/        // The module cache
3 /******/        var installedModules = {};
4
5 /******/        // The require function
6 /******/        function __webpack_require__(moduleId) {
7
8 /******/                // Check if module is in cache
9 /******/                if(installedModules[moduleId])
10 /******/                        return installedModules[moduleId].exports;
11
12 /******/                // Create a new module (and put it into the cache)
13 /******/                var module = installedModules[moduleId] = {
14 /******/                        exports: {},
15 /******/                        id: moduleId,
16 /******/                        loaded: false
17 /******/                };
18
19 /******/                // Execute the module function
20 /******/                modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21
22 /******/                // Flag the module as loaded
23 /******/                module.loaded = true;
24
25 /******/                // Return the exports of the module
26 /******/                return module.exports;
27 /******/        }
28
29
30 /******/        // expose the modules object (__webpack_modules__)
31 /******/        __webpack_require__.m = modules;
32
33 /******/        // expose the module cache
34 /******/        __webpack_require__.c = installedModules;
35
36 /******/        // __webpack_public_path__
37 /******/        __webpack_require__.p = "";
38
39 /******/        // Load entry module and return exports
40 /******/        return __webpack_require__(0);
41 /******/ })
42 /************************************************************************/
43 /******/ ([
44 /* 0 */
45 /***/ function(module, exports, __webpack_require__) {
46
47         __webpack_require__(1);
48         __webpack_require__(3);
49         __webpack_require__(4);
50         __webpack_require__(6);
51         __webpack_require__(8);
52         __webpack_require__(9);
53         __webpack_require__(10);
54         __webpack_require__(11);
55         __webpack_require__(12);
56         __webpack_require__(13);
57         __webpack_require__(14);
58         __webpack_require__(15);
59         __webpack_require__(16);
60         __webpack_require__(17);
61         __webpack_require__(18);
62         __webpack_require__(19);
63         __webpack_require__(20);
64         __webpack_require__(21);
65         __webpack_require__(22);
66 <<<<<<< HEAD
67         __webpack_require__(23);
68         __webpack_require__(24);
69 =======
70 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
71
72
73 /***/ },
74 /* 1 */
75 /***/ function(module, exports, __webpack_require__) {
76
77         __webpack_require__(2);
78         module.exports = angular;
79
80
81 /***/ },
82 /* 2 */
83 /***/ function(module, exports) {
84
85         /**
86          * @license AngularJS v1.4.8
87          * (c) 2010-2015 Google, Inc. http://angularjs.org
88          * License: MIT
89          */
90         (function(window, document, undefined) {'use strict';
91
92         /**
93          * @description
94          *
95          * This object provides a utility for producing rich Error messages within
96          * Angular. It can be called as follows:
97          *
98          * var exampleMinErr = minErr('example');
99          * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
100          *
101          * The above creates an instance of minErr in the example namespace. The
102          * resulting error will have a namespaced error code of example.one.  The
103          * resulting error will replace {0} with the value of foo, and {1} with the
104          * value of bar. The object is not restricted in the number of arguments it can
105          * take.
106          *
107          * If fewer arguments are specified than necessary for interpolation, the extra
108          * interpolation markers will be preserved in the final string.
109          *
110          * Since data will be parsed statically during a build step, some restrictions
111          * are applied with respect to how minErr instances are created and called.
112          * Instances should have names of the form namespaceMinErr for a minErr created
113          * using minErr('namespace') . Error codes, namespaces and template strings
114          * should all be static strings, not variables or general expressions.
115          *
116          * @param {string} module The namespace to use for the new minErr instance.
117          * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
118          *   error from returned function, for cases when a particular type of error is useful.
119          * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
120          */
121
122         function minErr(module, ErrorConstructor) {
123           ErrorConstructor = ErrorConstructor || Error;
124           return function() {
125             var SKIP_INDEXES = 2;
126
127             var templateArgs = arguments,
128               code = templateArgs[0],
129               message = '[' + (module ? module + ':' : '') + code + '] ',
130               template = templateArgs[1],
131               paramPrefix, i;
132
133             message += template.replace(/\{\d+\}/g, function(match) {
134               var index = +match.slice(1, -1),
135                 shiftedIndex = index + SKIP_INDEXES;
136
137               if (shiftedIndex < templateArgs.length) {
138                 return toDebugString(templateArgs[shiftedIndex]);
139               }
140
141               return match;
142             });
143
144             message += '\nhttp://errors.angularjs.org/1.4.8/' +
145               (module ? module + '/' : '') + code;
146
147             for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
148               message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
149                 encodeURIComponent(toDebugString(templateArgs[i]));
150             }
151
152             return new ErrorConstructor(message);
153           };
154         }
155
156         /* We need to tell jshint what variables are being exported */
157         /* global angular: true,
158           msie: true,
159           jqLite: true,
160           jQuery: true,
161           slice: true,
162           splice: true,
163           push: true,
164           toString: true,
165           ngMinErr: true,
166           angularModule: true,
167           uid: true,
168           REGEX_STRING_REGEXP: true,
169           VALIDITY_STATE_PROPERTY: true,
170
171           lowercase: true,
172           uppercase: true,
173           manualLowercase: true,
174           manualUppercase: true,
175           nodeName_: true,
176           isArrayLike: true,
177           forEach: true,
178           forEachSorted: true,
179           reverseParams: true,
180           nextUid: true,
181           setHashKey: true,
182           extend: true,
183           toInt: true,
184           inherit: true,
185           merge: true,
186           noop: true,
187           identity: true,
188           valueFn: true,
189           isUndefined: true,
190           isDefined: true,
191           isObject: true,
192           isBlankObject: true,
193           isString: true,
194           isNumber: true,
195           isDate: true,
196           isArray: true,
197           isFunction: true,
198           isRegExp: true,
199           isWindow: true,
200           isScope: true,
201           isFile: true,
202           isFormData: true,
203           isBlob: true,
204           isBoolean: true,
205           isPromiseLike: true,
206           trim: true,
207           escapeForRegexp: true,
208           isElement: true,
209           makeMap: true,
210           includes: true,
211           arrayRemove: true,
212           copy: true,
213           shallowCopy: true,
214           equals: true,
215           csp: true,
216           jq: true,
217           concat: true,
218           sliceArgs: true,
219           bind: true,
220           toJsonReplacer: true,
221           toJson: true,
222           fromJson: true,
223           convertTimezoneToLocal: true,
224           timezoneToOffset: true,
225           startingTag: true,
226           tryDecodeURIComponent: true,
227           parseKeyValue: true,
228           toKeyValue: true,
229           encodeUriSegment: true,
230           encodeUriQuery: true,
231           angularInit: true,
232           bootstrap: true,
233           getTestability: true,
234           snake_case: true,
235           bindJQuery: true,
236           assertArg: true,
237           assertArgFn: true,
238           assertNotHasOwnProperty: true,
239           getter: true,
240           getBlockNodes: true,
241           hasOwnProperty: true,
242           createMap: true,
243
244           NODE_TYPE_ELEMENT: true,
245           NODE_TYPE_ATTRIBUTE: true,
246           NODE_TYPE_TEXT: true,
247           NODE_TYPE_COMMENT: true,
248           NODE_TYPE_DOCUMENT: true,
249           NODE_TYPE_DOCUMENT_FRAGMENT: true,
250         */
251
252         ////////////////////////////////////
253
254         /**
255          * @ngdoc module
256          * @name ng
257          * @module ng
258          * @description
259          *
260          * # ng (core module)
261          * The ng module is loaded by default when an AngularJS application is started. The module itself
262          * contains the essential components for an AngularJS application to function. The table below
263          * lists a high level breakdown of each of the services/factories, filters, directives and testing
264          * components available within this core module.
265          *
266          * <div doc-module-components="ng"></div>
267          */
268
269         var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
270
271         // The name of a form control's ValidityState property.
272         // This is used so that it's possible for internal tests to create mock ValidityStates.
273         var VALIDITY_STATE_PROPERTY = 'validity';
274
275         /**
276          * @ngdoc function
277          * @name angular.lowercase
278          * @module ng
279          * @kind function
280          *
281          * @description Converts the specified string to lowercase.
282          * @param {string} string String to be converted to lowercase.
283          * @returns {string} Lowercased string.
284          */
285         var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
286         var hasOwnProperty = Object.prototype.hasOwnProperty;
287
288         /**
289          * @ngdoc function
290          * @name angular.uppercase
291          * @module ng
292          * @kind function
293          *
294          * @description Converts the specified string to uppercase.
295          * @param {string} string String to be converted to uppercase.
296          * @returns {string} Uppercased string.
297          */
298         var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
299
300
301         var manualLowercase = function(s) {
302           /* jshint bitwise: false */
303           return isString(s)
304               ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
305               : s;
306         };
307         var manualUppercase = function(s) {
308           /* jshint bitwise: false */
309           return isString(s)
310               ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
311               : s;
312         };
313
314
315         // String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
316         // locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
317         // with correct but slower alternatives.
318         if ('i' !== 'I'.toLowerCase()) {
319           lowercase = manualLowercase;
320           uppercase = manualUppercase;
321         }
322
323
324         var
325             msie,             // holds major version number for IE, or NaN if UA is not IE.
326             jqLite,           // delay binding since jQuery could be loaded after us.
327             jQuery,           // delay binding
328             slice             = [].slice,
329             splice            = [].splice,
330             push              = [].push,
331             toString          = Object.prototype.toString,
332             getPrototypeOf    = Object.getPrototypeOf,
333             ngMinErr          = minErr('ng'),
334
335             /** @name angular */
336             angular           = window.angular || (window.angular = {}),
337             angularModule,
338             uid               = 0;
339
340         /**
341          * documentMode is an IE-only property
342          * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
343          */
344         msie = document.documentMode;
345
346
347         /**
348          * @private
349          * @param {*} obj
350          * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
351          *                   String ...)
352          */
353         function isArrayLike(obj) {
354
355           // `null`, `undefined` and `window` are not array-like
356           if (obj == null || isWindow(obj)) return false;
357
358           // arrays, strings and jQuery/jqLite objects are array like
359           // * jqLite is either the jQuery or jqLite constructor function
360           // * we have to check the existance of jqLite first as this method is called
361           //   via the forEach method when constructing the jqLite object in the first place
362           if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
363
364           // Support: iOS 8.2 (not reproducible in simulator)
365           // "length" in obj used to prevent JIT error (gh-11508)
366           var length = "length" in Object(obj) && obj.length;
367
368           // NodeList objects (with `item` method) and
369           // other objects with suitable length characteristics are array-like
370           return isNumber(length) &&
371             (length >= 0 && (length - 1) in obj || typeof obj.item == 'function');
372         }
373
374         /**
375          * @ngdoc function
376          * @name angular.forEach
377          * @module ng
378          * @kind function
379          *
380          * @description
381          * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
382          * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
383          * is the value of an object property or an array element, `key` is the object property key or
384          * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
385          *
386          * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
387          * using the `hasOwnProperty` method.
388          *
389          * Unlike ES262's
390          * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
391          * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
392          * return the value provided.
393          *
394            ```js
395              var values = {name: 'misko', gender: 'male'};
396              var log = [];
397              angular.forEach(values, function(value, key) {
398                this.push(key + ': ' + value);
399              }, log);
400              expect(log).toEqual(['name: misko', 'gender: male']);
401            ```
402          *
403          * @param {Object|Array} obj Object to iterate over.
404          * @param {Function} iterator Iterator function.
405          * @param {Object=} context Object to become context (`this`) for the iterator function.
406          * @returns {Object|Array} Reference to `obj`.
407          */
408
409         function forEach(obj, iterator, context) {
410           var key, length;
411           if (obj) {
412             if (isFunction(obj)) {
413               for (key in obj) {
414                 // Need to check if hasOwnProperty exists,
415                 // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
416                 if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
417                   iterator.call(context, obj[key], key, obj);
418                 }
419               }
420             } else if (isArray(obj) || isArrayLike(obj)) {
421               var isPrimitive = typeof obj !== 'object';
422               for (key = 0, length = obj.length; key < length; key++) {
423                 if (isPrimitive || key in obj) {
424                   iterator.call(context, obj[key], key, obj);
425                 }
426               }
427             } else if (obj.forEach && obj.forEach !== forEach) {
428                 obj.forEach(iterator, context, obj);
429             } else if (isBlankObject(obj)) {
430               // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
431               for (key in obj) {
432                 iterator.call(context, obj[key], key, obj);
433               }
434             } else if (typeof obj.hasOwnProperty === 'function') {
435               // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
436               for (key in obj) {
437                 if (obj.hasOwnProperty(key)) {
438                   iterator.call(context, obj[key], key, obj);
439                 }
440               }
441             } else {
442               // Slow path for objects which do not have a method `hasOwnProperty`
443               for (key in obj) {
444                 if (hasOwnProperty.call(obj, key)) {
445                   iterator.call(context, obj[key], key, obj);
446                 }
447               }
448             }
449           }
450           return obj;
451         }
452
453         function forEachSorted(obj, iterator, context) {
454           var keys = Object.keys(obj).sort();
455           for (var i = 0; i < keys.length; i++) {
456             iterator.call(context, obj[keys[i]], keys[i]);
457           }
458           return keys;
459         }
460
461
462         /**
463          * when using forEach the params are value, key, but it is often useful to have key, value.
464          * @param {function(string, *)} iteratorFn
465          * @returns {function(*, string)}
466          */
467         function reverseParams(iteratorFn) {
468           return function(value, key) { iteratorFn(key, value); };
469         }
470
471         /**
472          * A consistent way of creating unique IDs in angular.
473          *
474          * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
475          * we hit number precision issues in JavaScript.
476          *
477          * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
478          *
479          * @returns {number} an unique alpha-numeric string
480          */
481         function nextUid() {
482           return ++uid;
483         }
484
485
486         /**
487          * Set or clear the hashkey for an object.
488          * @param obj object
489          * @param h the hashkey (!truthy to delete the hashkey)
490          */
491         function setHashKey(obj, h) {
492           if (h) {
493             obj.$$hashKey = h;
494           } else {
495             delete obj.$$hashKey;
496           }
497         }
498
499
500         function baseExtend(dst, objs, deep) {
501           var h = dst.$$hashKey;
502
503           for (var i = 0, ii = objs.length; i < ii; ++i) {
504             var obj = objs[i];
505             if (!isObject(obj) && !isFunction(obj)) continue;
506             var keys = Object.keys(obj);
507             for (var j = 0, jj = keys.length; j < jj; j++) {
508               var key = keys[j];
509               var src = obj[key];
510
511               if (deep && isObject(src)) {
512                 if (isDate(src)) {
513                   dst[key] = new Date(src.valueOf());
514                 } else if (isRegExp(src)) {
515                   dst[key] = new RegExp(src);
516                 } else if (src.nodeName) {
517                   dst[key] = src.cloneNode(true);
518                 } else if (isElement(src)) {
519                   dst[key] = src.clone();
520                 } else {
521                   if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
522                   baseExtend(dst[key], [src], true);
523                 }
524               } else {
525                 dst[key] = src;
526               }
527             }
528           }
529
530           setHashKey(dst, h);
531           return dst;
532         }
533
534         /**
535          * @ngdoc function
536          * @name angular.extend
537          * @module ng
538          * @kind function
539          *
540          * @description
541          * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
542          * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
543          * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
544          *
545          * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
546          * {@link angular.merge} for this.
547          *
548          * @param {Object} dst Destination object.
549          * @param {...Object} src Source object(s).
550          * @returns {Object} Reference to `dst`.
551          */
552         function extend(dst) {
553           return baseExtend(dst, slice.call(arguments, 1), false);
554         }
555
556
557         /**
558         * @ngdoc function
559         * @name angular.merge
560         * @module ng
561         * @kind function
562         *
563         * @description
564         * Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
565         * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
566         * by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
567         *
568         * Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
569         * objects, performing a deep copy.
570         *
571         * @param {Object} dst Destination object.
572         * @param {...Object} src Source object(s).
573         * @returns {Object} Reference to `dst`.
574         */
575         function merge(dst) {
576           return baseExtend(dst, slice.call(arguments, 1), true);
577         }
578
579
580
581         function toInt(str) {
582           return parseInt(str, 10);
583         }
584
585
586         function inherit(parent, extra) {
587           return extend(Object.create(parent), extra);
588         }
589
590         /**
591          * @ngdoc function
592          * @name angular.noop
593          * @module ng
594          * @kind function
595          *
596          * @description
597          * A function that performs no operations. This function can be useful when writing code in the
598          * functional style.
599            ```js
600              function foo(callback) {
601                var result = calculateResult();
602                (callback || angular.noop)(result);
603              }
604            ```
605          */
606         function noop() {}
607         noop.$inject = [];
608
609
610         /**
611          * @ngdoc function
612          * @name angular.identity
613          * @module ng
614          * @kind function
615          *
616          * @description
617          * A function that returns its first argument. This function is useful when writing code in the
618          * functional style.
619          *
620            ```js
621              function transformer(transformationFn, value) {
622                return (transformationFn || angular.identity)(value);
623              };
624            ```
625           * @param {*} value to be returned.
626           * @returns {*} the value passed in.
627          */
628         function identity($) {return $;}
629         identity.$inject = [];
630
631
632         function valueFn(value) {return function() {return value;};}
633
634         function hasCustomToString(obj) {
635           return isFunction(obj.toString) && obj.toString !== toString;
636         }
637
638
639         /**
640          * @ngdoc function
641          * @name angular.isUndefined
642          * @module ng
643          * @kind function
644          *
645          * @description
646          * Determines if a reference is undefined.
647          *
648          * @param {*} value Reference to check.
649          * @returns {boolean} True if `value` is undefined.
650          */
651         function isUndefined(value) {return typeof value === 'undefined';}
652
653
654         /**
655          * @ngdoc function
656          * @name angular.isDefined
657          * @module ng
658          * @kind function
659          *
660          * @description
661          * Determines if a reference is defined.
662          *
663          * @param {*} value Reference to check.
664          * @returns {boolean} True if `value` is defined.
665          */
666         function isDefined(value) {return typeof value !== 'undefined';}
667
668
669         /**
670          * @ngdoc function
671          * @name angular.isObject
672          * @module ng
673          * @kind function
674          *
675          * @description
676          * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
677          * considered to be objects. Note that JavaScript arrays are objects.
678          *
679          * @param {*} value Reference to check.
680          * @returns {boolean} True if `value` is an `Object` but not `null`.
681          */
682         function isObject(value) {
683           // http://jsperf.com/isobject4
684           return value !== null && typeof value === 'object';
685         }
686
687
688         /**
689          * Determine if a value is an object with a null prototype
690          *
691          * @returns {boolean} True if `value` is an `Object` with a null prototype
692          */
693         function isBlankObject(value) {
694           return value !== null && typeof value === 'object' && !getPrototypeOf(value);
695         }
696
697
698         /**
699          * @ngdoc function
700          * @name angular.isString
701          * @module ng
702          * @kind function
703          *
704          * @description
705          * Determines if a reference is a `String`.
706          *
707          * @param {*} value Reference to check.
708          * @returns {boolean} True if `value` is a `String`.
709          */
710         function isString(value) {return typeof value === 'string';}
711
712
713         /**
714          * @ngdoc function
715          * @name angular.isNumber
716          * @module ng
717          * @kind function
718          *
719          * @description
720          * Determines if a reference is a `Number`.
721          *
722          * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
723          *
724          * If you wish to exclude these then you can use the native
725          * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
726          * method.
727          *
728          * @param {*} value Reference to check.
729          * @returns {boolean} True if `value` is a `Number`.
730          */
731         function isNumber(value) {return typeof value === 'number';}
732
733
734         /**
735          * @ngdoc function
736          * @name angular.isDate
737          * @module ng
738          * @kind function
739          *
740          * @description
741          * Determines if a value is a date.
742          *
743          * @param {*} value Reference to check.
744          * @returns {boolean} True if `value` is a `Date`.
745          */
746         function isDate(value) {
747           return toString.call(value) === '[object Date]';
748         }
749
750
751         /**
752          * @ngdoc function
753          * @name angular.isArray
754          * @module ng
755          * @kind function
756          *
757          * @description
758          * Determines if a reference is an `Array`.
759          *
760          * @param {*} value Reference to check.
761          * @returns {boolean} True if `value` is an `Array`.
762          */
763         var isArray = Array.isArray;
764
765         /**
766          * @ngdoc function
767          * @name angular.isFunction
768          * @module ng
769          * @kind function
770          *
771          * @description
772          * Determines if a reference is a `Function`.
773          *
774          * @param {*} value Reference to check.
775          * @returns {boolean} True if `value` is a `Function`.
776          */
777         function isFunction(value) {return typeof value === 'function';}
778
779
780         /**
781          * Determines if a value is a regular expression object.
782          *
783          * @private
784          * @param {*} value Reference to check.
785          * @returns {boolean} True if `value` is a `RegExp`.
786          */
787         function isRegExp(value) {
788           return toString.call(value) === '[object RegExp]';
789         }
790
791
792         /**
793          * Checks if `obj` is a window object.
794          *
795          * @private
796          * @param {*} obj Object to check
797          * @returns {boolean} True if `obj` is a window obj.
798          */
799         function isWindow(obj) {
800           return obj && obj.window === obj;
801         }
802
803
804         function isScope(obj) {
805           return obj && obj.$evalAsync && obj.$watch;
806         }
807
808
809         function isFile(obj) {
810           return toString.call(obj) === '[object File]';
811         }
812
813
814         function isFormData(obj) {
815           return toString.call(obj) === '[object FormData]';
816         }
817
818
819         function isBlob(obj) {
820           return toString.call(obj) === '[object Blob]';
821         }
822
823
824         function isBoolean(value) {
825           return typeof value === 'boolean';
826         }
827
828
829         function isPromiseLike(obj) {
830           return obj && isFunction(obj.then);
831         }
832
833
834         var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
835         function isTypedArray(value) {
836           return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
837         }
838
839
840         var trim = function(value) {
841           return isString(value) ? value.trim() : value;
842         };
843
844         // Copied from:
845         // http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
846         // Prereq: s is a string.
847         var escapeForRegexp = function(s) {
848           return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
849                    replace(/\x08/g, '\\x08');
850         };
851
852
853         /**
854          * @ngdoc function
855          * @name angular.isElement
856          * @module ng
857          * @kind function
858          *
859          * @description
860          * Determines if a reference is a DOM element (or wrapped jQuery element).
861          *
862          * @param {*} value Reference to check.
863          * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
864          */
865         function isElement(node) {
866           return !!(node &&
867             (node.nodeName  // we are a direct element
868             || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API
869         }
870
871         /**
872          * @param str 'key1,key2,...'
873          * @returns {object} in the form of {key1:true, key2:true, ...}
874          */
875         function makeMap(str) {
876           var obj = {}, items = str.split(","), i;
877           for (i = 0; i < items.length; i++) {
878             obj[items[i]] = true;
879           }
880           return obj;
881         }
882
883
884         function nodeName_(element) {
885           return lowercase(element.nodeName || (element[0] && element[0].nodeName));
886         }
887
888         function includes(array, obj) {
889           return Array.prototype.indexOf.call(array, obj) != -1;
890         }
891
892         function arrayRemove(array, value) {
893           var index = array.indexOf(value);
894           if (index >= 0) {
895             array.splice(index, 1);
896           }
897           return index;
898         }
899
900         /**
901          * @ngdoc function
902          * @name angular.copy
903          * @module ng
904          * @kind function
905          *
906          * @description
907          * Creates a deep copy of `source`, which should be an object or an array.
908          *
909          * * If no destination is supplied, a copy of the object or array is created.
910          * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
911          *   are deleted and then all elements/properties from the source are copied to it.
912          * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
913          * * If `source` is identical to 'destination' an exception will be thrown.
914          *
915          * @param {*} source The source that will be used to make a copy.
916          *                   Can be any type, including primitives, `null`, and `undefined`.
917          * @param {(Object|Array)=} destination Destination into which the source is copied. If
918          *     provided, must be of the same type as `source`.
919          * @returns {*} The copy or updated `destination`, if `destination` was specified.
920          *
921          * @example
922          <example module="copyExample">
923          <file name="index.html">
924          <div ng-controller="ExampleController">
925          <form novalidate class="simple-form">
926          Name: <input type="text" ng-model="user.name" /><br />
927          E-mail: <input type="email" ng-model="user.email" /><br />
928          Gender: <input type="radio" ng-model="user.gender" value="male" />male
929          <input type="radio" ng-model="user.gender" value="female" />female<br />
930          <button ng-click="reset()">RESET</button>
931          <button ng-click="update(user)">SAVE</button>
932          </form>
933          <pre>form = {{user | json}}</pre>
934          <pre>master = {{master | json}}</pre>
935          </div>
936
937          <script>
938           angular.module('copyExample', [])
939             .controller('ExampleController', ['$scope', function($scope) {
940               $scope.master= {};
941
942               $scope.update = function(user) {
943                 // Example with 1 argument
944                 $scope.master= angular.copy(user);
945               };
946
947               $scope.reset = function() {
948                 // Example with 2 arguments
949                 angular.copy($scope.master, $scope.user);
950               };
951
952               $scope.reset();
953             }]);
954          </script>
955          </file>
956          </example>
957          */
958         function copy(source, destination) {
959           var stackSource = [];
960           var stackDest = [];
961
962           if (destination) {
963             if (isTypedArray(destination)) {
964               throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
965             }
966             if (source === destination) {
967               throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
968             }
969
970             // Empty the destination object
971             if (isArray(destination)) {
972               destination.length = 0;
973             } else {
974               forEach(destination, function(value, key) {
975                 if (key !== '$$hashKey') {
976                   delete destination[key];
977                 }
978               });
979             }
980
981             stackSource.push(source);
982             stackDest.push(destination);
983             return copyRecurse(source, destination);
984           }
985
986           return copyElement(source);
987
988           function copyRecurse(source, destination) {
989             var h = destination.$$hashKey;
990             var result, key;
991             if (isArray(source)) {
992               for (var i = 0, ii = source.length; i < ii; i++) {
993                 destination.push(copyElement(source[i]));
994               }
995             } else if (isBlankObject(source)) {
996               // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
997               for (key in source) {
998                 destination[key] = copyElement(source[key]);
999               }
1000             } else if (source && typeof source.hasOwnProperty === 'function') {
1001               // Slow path, which must rely on hasOwnProperty
1002               for (key in source) {
1003                 if (source.hasOwnProperty(key)) {
1004                   destination[key] = copyElement(source[key]);
1005                 }
1006               }
1007             } else {
1008               // Slowest path --- hasOwnProperty can't be called as a method
1009               for (key in source) {
1010                 if (hasOwnProperty.call(source, key)) {
1011                   destination[key] = copyElement(source[key]);
1012                 }
1013               }
1014             }
1015             setHashKey(destination, h);
1016             return destination;
1017           }
1018
1019           function copyElement(source) {
1020             // Simple values
1021             if (!isObject(source)) {
1022               return source;
1023             }
1024
1025             // Already copied values
1026             var index = stackSource.indexOf(source);
1027             if (index !== -1) {
1028               return stackDest[index];
1029             }
1030
1031             if (isWindow(source) || isScope(source)) {
1032               throw ngMinErr('cpws',
1033                 "Can't copy! Making copies of Window or Scope instances is not supported.");
1034             }
1035
1036             var needsRecurse = false;
1037             var destination;
1038
1039             if (isArray(source)) {
1040               destination = [];
1041               needsRecurse = true;
1042             } else if (isTypedArray(source)) {
1043               destination = new source.constructor(source);
1044             } else if (isDate(source)) {
1045               destination = new Date(source.getTime());
1046             } else if (isRegExp(source)) {
1047               destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
1048               destination.lastIndex = source.lastIndex;
1049             } else if (isFunction(source.cloneNode)) {
1050                 destination = source.cloneNode(true);
1051             } else {
1052               destination = Object.create(getPrototypeOf(source));
1053               needsRecurse = true;
1054             }
1055
1056             stackSource.push(source);
1057             stackDest.push(destination);
1058
1059             return needsRecurse
1060               ? copyRecurse(source, destination)
1061               : destination;
1062           }
1063         }
1064
1065         /**
1066          * Creates a shallow copy of an object, an array or a primitive.
1067          *
1068          * Assumes that there are no proto properties for objects.
1069          */
1070         function shallowCopy(src, dst) {
1071           if (isArray(src)) {
1072             dst = dst || [];
1073
1074             for (var i = 0, ii = src.length; i < ii; i++) {
1075               dst[i] = src[i];
1076             }
1077           } else if (isObject(src)) {
1078             dst = dst || {};
1079
1080             for (var key in src) {
1081               if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
1082                 dst[key] = src[key];
1083               }
1084             }
1085           }
1086
1087           return dst || src;
1088         }
1089
1090
1091         /**
1092          * @ngdoc function
1093          * @name angular.equals
1094          * @module ng
1095          * @kind function
1096          *
1097          * @description
1098          * Determines if two objects or two values are equivalent. Supports value types, regular
1099          * expressions, arrays and objects.
1100          *
1101          * Two objects or values are considered equivalent if at least one of the following is true:
1102          *
1103          * * Both objects or values pass `===` comparison.
1104          * * Both objects or values are of the same type and all of their properties are equal by
1105          *   comparing them with `angular.equals`.
1106          * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
1107          * * Both values represent the same regular expression (In JavaScript,
1108          *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
1109          *   representation matches).
1110          *
1111          * During a property comparison, properties of `function` type and properties with names
1112          * that begin with `$` are ignored.
1113          *
1114          * Scope and DOMWindow objects are being compared only by identify (`===`).
1115          *
1116          * @param {*} o1 Object or value to compare.
1117          * @param {*} o2 Object or value to compare.
1118          * @returns {boolean} True if arguments are equal.
1119          */
1120         function equals(o1, o2) {
1121           if (o1 === o2) return true;
1122           if (o1 === null || o2 === null) return false;
1123           if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
1124           var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
1125           if (t1 == t2) {
1126             if (t1 == 'object') {
1127               if (isArray(o1)) {
1128                 if (!isArray(o2)) return false;
1129                 if ((length = o1.length) == o2.length) {
1130                   for (key = 0; key < length; key++) {
1131                     if (!equals(o1[key], o2[key])) return false;
1132                   }
1133                   return true;
1134                 }
1135               } else if (isDate(o1)) {
1136                 if (!isDate(o2)) return false;
1137                 return equals(o1.getTime(), o2.getTime());
1138               } else if (isRegExp(o1)) {
1139                 return isRegExp(o2) ? o1.toString() == o2.toString() : false;
1140               } else {
1141                 if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
1142                   isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
1143                 keySet = createMap();
1144                 for (key in o1) {
1145                   if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
1146                   if (!equals(o1[key], o2[key])) return false;
1147                   keySet[key] = true;
1148                 }
1149                 for (key in o2) {
1150                   if (!(key in keySet) &&
1151                       key.charAt(0) !== '$' &&
1152                       isDefined(o2[key]) &&
1153                       !isFunction(o2[key])) return false;
1154                 }
1155                 return true;
1156               }
1157             }
1158           }
1159           return false;
1160         }
1161
1162         var csp = function() {
1163           if (!isDefined(csp.rules)) {
1164
1165
1166             var ngCspElement = (document.querySelector('[ng-csp]') ||
1167                             document.querySelector('[data-ng-csp]'));
1168
1169             if (ngCspElement) {
1170               var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
1171                             ngCspElement.getAttribute('data-ng-csp');
1172               csp.rules = {
1173                 noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),
1174                 noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)
1175               };
1176             } else {
1177               csp.rules = {
1178                 noUnsafeEval: noUnsafeEval(),
1179                 noInlineStyle: false
1180               };
1181             }
1182           }
1183
1184           return csp.rules;
1185
1186           function noUnsafeEval() {
1187             try {
1188               /* jshint -W031, -W054 */
1189               new Function('');
1190               /* jshint +W031, +W054 */
1191               return false;
1192             } catch (e) {
1193               return true;
1194             }
1195           }
1196         };
1197
1198         /**
1199          * @ngdoc directive
1200          * @module ng
1201          * @name ngJq
1202          *
1203          * @element ANY
1204          * @param {string=} ngJq the name of the library available under `window`
1205          * to be used for angular.element
1206          * @description
1207          * Use this directive to force the angular.element library.  This should be
1208          * used to force either jqLite by leaving ng-jq blank or setting the name of
1209          * the jquery variable under window (eg. jQuery).
1210          *
1211          * Since angular looks for this directive when it is loaded (doesn't wait for the
1212          * DOMContentLoaded event), it must be placed on an element that comes before the script
1213          * which loads angular. Also, only the first instance of `ng-jq` will be used and all
1214          * others ignored.
1215          *
1216          * @example
1217          * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
1218          ```html
1219          <!doctype html>
1220          <html ng-app ng-jq>
1221          ...
1222          ...
1223          </html>
1224          ```
1225          * @example
1226          * This example shows how to use a jQuery based library of a different name.
1227          * The library name must be available at the top most 'window'.
1228          ```html
1229          <!doctype html>
1230          <html ng-app ng-jq="jQueryLib">
1231          ...
1232          ...
1233          </html>
1234          ```
1235          */
1236         var jq = function() {
1237           if (isDefined(jq.name_)) return jq.name_;
1238           var el;
1239           var i, ii = ngAttrPrefixes.length, prefix, name;
1240           for (i = 0; i < ii; ++i) {
1241             prefix = ngAttrPrefixes[i];
1242             if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
1243               name = el.getAttribute(prefix + 'jq');
1244               break;
1245             }
1246           }
1247
1248           return (jq.name_ = name);
1249         };
1250
1251         function concat(array1, array2, index) {
1252           return array1.concat(slice.call(array2, index));
1253         }
1254
1255         function sliceArgs(args, startIndex) {
1256           return slice.call(args, startIndex || 0);
1257         }
1258
1259
1260         /* jshint -W101 */
1261         /**
1262          * @ngdoc function
1263          * @name angular.bind
1264          * @module ng
1265          * @kind function
1266          *
1267          * @description
1268          * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
1269          * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
1270          * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
1271          * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
1272          *
1273          * @param {Object} self Context which `fn` should be evaluated in.
1274          * @param {function()} fn Function to be bound.
1275          * @param {...*} args Optional arguments to be prebound to the `fn` function call.
1276          * @returns {function()} Function that wraps the `fn` with all the specified bindings.
1277          */
1278         /* jshint +W101 */
1279         function bind(self, fn) {
1280           var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
1281           if (isFunction(fn) && !(fn instanceof RegExp)) {
1282             return curryArgs.length
1283               ? function() {
1284                   return arguments.length
1285                     ? fn.apply(self, concat(curryArgs, arguments, 0))
1286                     : fn.apply(self, curryArgs);
1287                 }
1288               : function() {
1289                   return arguments.length
1290                     ? fn.apply(self, arguments)
1291                     : fn.call(self);
1292                 };
1293           } else {
1294             // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
1295             return fn;
1296           }
1297         }
1298
1299
1300         function toJsonReplacer(key, value) {
1301           var val = value;
1302
1303           if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
1304             val = undefined;
1305           } else if (isWindow(value)) {
1306             val = '$WINDOW';
1307           } else if (value &&  document === value) {
1308             val = '$DOCUMENT';
1309           } else if (isScope(value)) {
1310             val = '$SCOPE';
1311           }
1312
1313           return val;
1314         }
1315
1316
1317         /**
1318          * @ngdoc function
1319          * @name angular.toJson
1320          * @module ng
1321          * @kind function
1322          *
1323          * @description
1324          * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
1325          * stripped since angular uses this notation internally.
1326          *
1327          * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
1328          * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
1329          *    If set to an integer, the JSON output will contain that many spaces per indentation.
1330          * @returns {string|undefined} JSON-ified string representing `obj`.
1331          */
1332         function toJson(obj, pretty) {
1333           if (typeof obj === 'undefined') return undefined;
1334           if (!isNumber(pretty)) {
1335             pretty = pretty ? 2 : null;
1336           }
1337           return JSON.stringify(obj, toJsonReplacer, pretty);
1338         }
1339
1340
1341         /**
1342          * @ngdoc function
1343          * @name angular.fromJson
1344          * @module ng
1345          * @kind function
1346          *
1347          * @description
1348          * Deserializes a JSON string.
1349          *
1350          * @param {string} json JSON string to deserialize.
1351          * @returns {Object|Array|string|number} Deserialized JSON string.
1352          */
1353         function fromJson(json) {
1354           return isString(json)
1355               ? JSON.parse(json)
1356               : json;
1357         }
1358
1359
1360         function timezoneToOffset(timezone, fallback) {
1361           var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
1362           return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
1363         }
1364
1365
1366         function addDateMinutes(date, minutes) {
1367           date = new Date(date.getTime());
1368           date.setMinutes(date.getMinutes() + minutes);
1369           return date;
1370         }
1371
1372
1373         function convertTimezoneToLocal(date, timezone, reverse) {
1374           reverse = reverse ? -1 : 1;
1375           var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
1376           return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset()));
1377         }
1378
1379
1380         /**
1381          * @returns {string} Returns the string representation of the element.
1382          */
1383         function startingTag(element) {
1384           element = jqLite(element).clone();
1385           try {
1386             // turns out IE does not let you set .html() on elements which
1387             // are not allowed to have children. So we just ignore it.
1388             element.empty();
1389           } catch (e) {}
1390           var elemHtml = jqLite('<div>').append(element).html();
1391           try {
1392             return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
1393                 elemHtml.
1394                   match(/^(<[^>]+>)/)[1].
1395                   replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
1396           } catch (e) {
1397             return lowercase(elemHtml);
1398           }
1399
1400         }
1401
1402
1403         /////////////////////////////////////////////////
1404
1405         /**
1406          * Tries to decode the URI component without throwing an exception.
1407          *
1408          * @private
1409          * @param str value potential URI component to check.
1410          * @returns {boolean} True if `value` can be decoded
1411          * with the decodeURIComponent function.
1412          */
1413         function tryDecodeURIComponent(value) {
1414           try {
1415             return decodeURIComponent(value);
1416           } catch (e) {
1417             // Ignore any invalid uri component
1418           }
1419         }
1420
1421
1422         /**
1423          * Parses an escaped url query string into key-value pairs.
1424          * @returns {Object.<string,boolean|Array>}
1425          */
1426         function parseKeyValue(/**string*/keyValue) {
1427           var obj = {};
1428           forEach((keyValue || "").split('&'), function(keyValue) {
1429             var splitPoint, key, val;
1430             if (keyValue) {
1431               key = keyValue = keyValue.replace(/\+/g,'%20');
1432               splitPoint = keyValue.indexOf('=');
1433               if (splitPoint !== -1) {
1434                 key = keyValue.substring(0, splitPoint);
1435                 val = keyValue.substring(splitPoint + 1);
1436               }
1437               key = tryDecodeURIComponent(key);
1438               if (isDefined(key)) {
1439                 val = isDefined(val) ? tryDecodeURIComponent(val) : true;
1440                 if (!hasOwnProperty.call(obj, key)) {
1441                   obj[key] = val;
1442                 } else if (isArray(obj[key])) {
1443                   obj[key].push(val);
1444                 } else {
1445                   obj[key] = [obj[key],val];
1446                 }
1447               }
1448             }
1449           });
1450           return obj;
1451         }
1452
1453         function toKeyValue(obj) {
1454           var parts = [];
1455           forEach(obj, function(value, key) {
1456             if (isArray(value)) {
1457               forEach(value, function(arrayValue) {
1458                 parts.push(encodeUriQuery(key, true) +
1459                            (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
1460               });
1461             } else {
1462             parts.push(encodeUriQuery(key, true) +
1463                        (value === true ? '' : '=' + encodeUriQuery(value, true)));
1464             }
1465           });
1466           return parts.length ? parts.join('&') : '';
1467         }
1468
1469
1470         /**
1471          * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
1472          * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
1473          * segments:
1474          *    segment       = *pchar
1475          *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
1476          *    pct-encoded   = "%" HEXDIG HEXDIG
1477          *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
1478          *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
1479          *                     / "*" / "+" / "," / ";" / "="
1480          */
1481         function encodeUriSegment(val) {
1482           return encodeUriQuery(val, true).
1483                      replace(/%26/gi, '&').
1484                      replace(/%3D/gi, '=').
1485                      replace(/%2B/gi, '+');
1486         }
1487
1488
1489         /**
1490          * This method is intended for encoding *key* or *value* parts of query component. We need a custom
1491          * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
1492          * encoded per http://tools.ietf.org/html/rfc3986:
1493          *    query       = *( pchar / "/" / "?" )
1494          *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
1495          *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
1496          *    pct-encoded   = "%" HEXDIG HEXDIG
1497          *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
1498          *                     / "*" / "+" / "," / ";" / "="
1499          */
1500         function encodeUriQuery(val, pctEncodeSpaces) {
1501           return encodeURIComponent(val).
1502                      replace(/%40/gi, '@').
1503                      replace(/%3A/gi, ':').
1504                      replace(/%24/g, '$').
1505                      replace(/%2C/gi, ',').
1506                      replace(/%3B/gi, ';').
1507                      replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
1508         }
1509
1510         var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
1511
1512         function getNgAttribute(element, ngAttr) {
1513           var attr, i, ii = ngAttrPrefixes.length;
1514           for (i = 0; i < ii; ++i) {
1515             attr = ngAttrPrefixes[i] + ngAttr;
1516             if (isString(attr = element.getAttribute(attr))) {
1517               return attr;
1518             }
1519           }
1520           return null;
1521         }
1522
1523         /**
1524          * @ngdoc directive
1525          * @name ngApp
1526          * @module ng
1527          *
1528          * @element ANY
1529          * @param {angular.Module} ngApp an optional application
1530          *   {@link angular.module module} name to load.
1531          * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
1532          *   created in "strict-di" mode. This means that the application will fail to invoke functions which
1533          *   do not use explicit function annotation (and are thus unsuitable for minification), as described
1534          *   in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
1535          *   tracking down the root of these bugs.
1536          *
1537          * @description
1538          *
1539          * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
1540          * designates the **root element** of the application and is typically placed near the root element
1541          * of the page - e.g. on the `<body>` or `<html>` tags.
1542          *
1543          * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
1544          * found in the document will be used to define the root element to auto-bootstrap as an
1545          * application. To run multiple applications in an HTML document you must manually bootstrap them using
1546          * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
1547          *
1548          * You can specify an **AngularJS module** to be used as the root module for the application.  This
1549          * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
1550          * should contain the application code needed or have dependencies on other modules that will
1551          * contain the code. See {@link angular.module} for more information.
1552          *
1553          * In the example below if the `ngApp` directive were not placed on the `html` element then the
1554          * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
1555          * would not be resolved to `3`.
1556          *
1557          * `ngApp` is the easiest, and most common way to bootstrap an application.
1558          *
1559          <example module="ngAppDemo">
1560            <file name="index.html">
1561            <div ng-controller="ngAppDemoController">
1562              I can add: {{a}} + {{b}} =  {{ a+b }}
1563            </div>
1564            </file>
1565            <file name="script.js">
1566            angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
1567              $scope.a = 1;
1568              $scope.b = 2;
1569            });
1570            </file>
1571          </example>
1572          *
1573          * Using `ngStrictDi`, you would see something like this:
1574          *
1575          <example ng-app-included="true">
1576            <file name="index.html">
1577            <div ng-app="ngAppStrictDemo" ng-strict-di>
1578                <div ng-controller="GoodController1">
1579                    I can add: {{a}} + {{b}} =  {{ a+b }}
1580
1581                    <p>This renders because the controller does not fail to
1582                       instantiate, by using explicit annotation style (see
1583                       script.js for details)
1584                    </p>
1585                </div>
1586
1587                <div ng-controller="GoodController2">
1588                    Name: <input ng-model="name"><br />
1589                    Hello, {{name}}!
1590
1591                    <p>This renders because the controller does not fail to
1592                       instantiate, by using explicit annotation style
1593                       (see script.js for details)
1594                    </p>
1595                </div>
1596
1597                <div ng-controller="BadController">
1598                    I can add: {{a}} + {{b}} =  {{ a+b }}
1599
1600                    <p>The controller could not be instantiated, due to relying
1601                       on automatic function annotations (which are disabled in
1602                       strict mode). As such, the content of this section is not
1603                       interpolated, and there should be an error in your web console.
1604                    </p>
1605                </div>
1606            </div>
1607            </file>
1608            <file name="script.js">
1609            angular.module('ngAppStrictDemo', [])
1610              // BadController will fail to instantiate, due to relying on automatic function annotation,
1611              // rather than an explicit annotation
1612              .controller('BadController', function($scope) {
1613                $scope.a = 1;
1614                $scope.b = 2;
1615              })
1616              // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
1617              // due to using explicit annotations using the array style and $inject property, respectively.
1618              .controller('GoodController1', ['$scope', function($scope) {
1619                $scope.a = 1;
1620                $scope.b = 2;
1621              }])
1622              .controller('GoodController2', GoodController2);
1623              function GoodController2($scope) {
1624                $scope.name = "World";
1625              }
1626              GoodController2.$inject = ['$scope'];
1627            </file>
1628            <file name="style.css">
1629            div[ng-controller] {
1630                margin-bottom: 1em;
1631                -webkit-border-radius: 4px;
1632                border-radius: 4px;
1633                border: 1px solid;
1634                padding: .5em;
1635            }
1636            div[ng-controller^=Good] {
1637                border-color: #d6e9c6;
1638                background-color: #dff0d8;
1639                color: #3c763d;
1640            }
1641            div[ng-controller^=Bad] {
1642                border-color: #ebccd1;
1643                background-color: #f2dede;
1644                color: #a94442;
1645                margin-bottom: 0;
1646            }
1647            </file>
1648          </example>
1649          */
1650         function angularInit(element, bootstrap) {
1651           var appElement,
1652               module,
1653               config = {};
1654
1655           // The element `element` has priority over any other element
1656           forEach(ngAttrPrefixes, function(prefix) {
1657             var name = prefix + 'app';
1658
1659             if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
1660               appElement = element;
1661               module = element.getAttribute(name);
1662             }
1663           });
1664           forEach(ngAttrPrefixes, function(prefix) {
1665             var name = prefix + 'app';
1666             var candidate;
1667
1668             if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
1669               appElement = candidate;
1670               module = candidate.getAttribute(name);
1671             }
1672           });
1673           if (appElement) {
1674             config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
1675             bootstrap(appElement, module ? [module] : [], config);
1676           }
1677         }
1678
1679         /**
1680          * @ngdoc function
1681          * @name angular.bootstrap
1682          * @module ng
1683          * @description
1684          * Use this function to manually start up angular application.
1685          *
1686          * See: {@link guide/bootstrap Bootstrap}
1687          *
1688          * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.
1689          * They must use {@link ng.directive:ngApp ngApp}.
1690          *
1691          * Angular will detect if it has been loaded into the browser more than once and only allow the
1692          * first loaded script to be bootstrapped and will report a warning to the browser console for
1693          * each of the subsequent scripts. This prevents strange results in applications, where otherwise
1694          * multiple instances of Angular try to work on the DOM.
1695          *
1696          * ```html
1697          * <!doctype html>
1698          * <html>
1699          * <body>
1700          * <div ng-controller="WelcomeController">
1701          *   {{greeting}}
1702          * </div>
1703          *
1704          * <script src="angular.js"></script>
1705          * <script>
1706          *   var app = angular.module('demo', [])
1707          *   .controller('WelcomeController', function($scope) {
1708          *       $scope.greeting = 'Welcome!';
1709          *   });
1710          *   angular.bootstrap(document, ['demo']);
1711          * </script>
1712          * </body>
1713          * </html>
1714          * ```
1715          *
1716          * @param {DOMElement} element DOM element which is the root of angular application.
1717          * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
1718          *     Each item in the array should be the name of a predefined module or a (DI annotated)
1719          *     function that will be invoked by the injector as a `config` block.
1720          *     See: {@link angular.module modules}
1721          * @param {Object=} config an object for defining configuration options for the application. The
1722          *     following keys are supported:
1723          *
1724          * * `strictDi` - disable automatic function annotation for the application. This is meant to
1725          *   assist in finding bugs which break minified code. Defaults to `false`.
1726          *
1727          * @returns {auto.$injector} Returns the newly created injector for this app.
1728          */
1729         function bootstrap(element, modules, config) {
1730           if (!isObject(config)) config = {};
1731           var defaultConfig = {
1732             strictDi: false
1733           };
1734           config = extend(defaultConfig, config);
1735           var doBootstrap = function() {
1736             element = jqLite(element);
1737
1738             if (element.injector()) {
1739               var tag = (element[0] === document) ? 'document' : startingTag(element);
1740               //Encode angle brackets to prevent input from being sanitized to empty string #8683
1741               throw ngMinErr(
1742                   'btstrpd',
1743                   "App Already Bootstrapped with this Element '{0}'",
1744                   tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
1745             }
1746
1747             modules = modules || [];
1748             modules.unshift(['$provide', function($provide) {
1749               $provide.value('$rootElement', element);
1750             }]);
1751
1752             if (config.debugInfoEnabled) {
1753               // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.
1754               modules.push(['$compileProvider', function($compileProvider) {
1755                 $compileProvider.debugInfoEnabled(true);
1756               }]);
1757             }
1758
1759             modules.unshift('ng');
1760             var injector = createInjector(modules, config.strictDi);
1761             injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
1762                function bootstrapApply(scope, element, compile, injector) {
1763                 scope.$apply(function() {
1764                   element.data('$injector', injector);
1765                   compile(element)(scope);
1766                 });
1767               }]
1768             );
1769             return injector;
1770           };
1771
1772           var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;
1773           var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
1774
1775           if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {
1776             config.debugInfoEnabled = true;
1777             window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');
1778           }
1779
1780           if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
1781             return doBootstrap();
1782           }
1783
1784           window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
1785           angular.resumeBootstrap = function(extraModules) {
1786             forEach(extraModules, function(module) {
1787               modules.push(module);
1788             });
1789             return doBootstrap();
1790           };
1791
1792           if (isFunction(angular.resumeDeferredBootstrap)) {
1793             angular.resumeDeferredBootstrap();
1794           }
1795         }
1796
1797         /**
1798          * @ngdoc function
1799          * @name angular.reloadWithDebugInfo
1800          * @module ng
1801          * @description
1802          * Use this function to reload the current application with debug information turned on.
1803          * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.
1804          *
1805          * See {@link ng.$compileProvider#debugInfoEnabled} for more.
1806          */
1807         function reloadWithDebugInfo() {
1808           window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
1809           window.location.reload();
1810         }
1811
1812         /**
1813          * @name angular.getTestability
1814          * @module ng
1815          * @description
1816          * Get the testability service for the instance of Angular on the given
1817          * element.
1818          * @param {DOMElement} element DOM element which is the root of angular application.
1819          */
1820         function getTestability(rootElement) {
1821           var injector = angular.element(rootElement).injector();
1822           if (!injector) {
1823             throw ngMinErr('test',
1824               'no injector found for element argument to getTestability');
1825           }
1826           return injector.get('$$testability');
1827         }
1828
1829         var SNAKE_CASE_REGEXP = /[A-Z]/g;
1830         function snake_case(name, separator) {
1831           separator = separator || '_';
1832           return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
1833             return (pos ? separator : '') + letter.toLowerCase();
1834           });
1835         }
1836
1837         var bindJQueryFired = false;
1838         var skipDestroyOnNextJQueryCleanData;
1839         function bindJQuery() {
1840           var originalCleanData;
1841
1842           if (bindJQueryFired) {
1843             return;
1844           }
1845
1846           // bind to jQuery if present;
1847           var jqName = jq();
1848           jQuery = isUndefined(jqName) ? window.jQuery :   // use jQuery (if present)
1849                    !jqName             ? undefined     :   // use jqLite
1850                                          window[jqName];   // use jQuery specified by `ngJq`
1851
1852           // Use jQuery if it exists with proper functionality, otherwise default to us.
1853           // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
1854           // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
1855           // versions. It will not work for sure with jQuery <1.7, though.
1856           if (jQuery && jQuery.fn.on) {
1857             jqLite = jQuery;
1858             extend(jQuery.fn, {
1859               scope: JQLitePrototype.scope,
1860               isolateScope: JQLitePrototype.isolateScope,
1861               controller: JQLitePrototype.controller,
1862               injector: JQLitePrototype.injector,
1863               inheritedData: JQLitePrototype.inheritedData
1864             });
1865
1866             // All nodes removed from the DOM via various jQuery APIs like .remove()
1867             // are passed through jQuery.cleanData. Monkey-patch this method to fire
1868             // the $destroy event on all removed nodes.
1869             originalCleanData = jQuery.cleanData;
1870             jQuery.cleanData = function(elems) {
1871               var events;
1872               if (!skipDestroyOnNextJQueryCleanData) {
1873                 for (var i = 0, elem; (elem = elems[i]) != null; i++) {
1874                   events = jQuery._data(elem, "events");
1875                   if (events && events.$destroy) {
1876                     jQuery(elem).triggerHandler('$destroy');
1877                   }
1878                 }
1879               } else {
1880                 skipDestroyOnNextJQueryCleanData = false;
1881               }
1882               originalCleanData(elems);
1883             };
1884           } else {
1885             jqLite = JQLite;
1886           }
1887
1888           angular.element = jqLite;
1889
1890           // Prevent double-proxying.
1891           bindJQueryFired = true;
1892         }
1893
1894         /**
1895          * throw error if the argument is falsy.
1896          */
1897         function assertArg(arg, name, reason) {
1898           if (!arg) {
1899             throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
1900           }
1901           return arg;
1902         }
1903
1904         function assertArgFn(arg, name, acceptArrayAnnotation) {
1905           if (acceptArrayAnnotation && isArray(arg)) {
1906               arg = arg[arg.length - 1];
1907           }
1908
1909           assertArg(isFunction(arg), name, 'not a function, got ' +
1910               (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
1911           return arg;
1912         }
1913
1914         /**
1915          * throw error if the name given is hasOwnProperty
1916          * @param  {String} name    the name to test
1917          * @param  {String} context the context in which the name is used, such as module or directive
1918          */
1919         function assertNotHasOwnProperty(name, context) {
1920           if (name === 'hasOwnProperty') {
1921             throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
1922           }
1923         }
1924
1925         /**
1926          * Return the value accessible from the object by path. Any undefined traversals are ignored
1927          * @param {Object} obj starting object
1928          * @param {String} path path to traverse
1929          * @param {boolean} [bindFnToScope=true]
1930          * @returns {Object} value as accessible by path
1931          */
1932         //TODO(misko): this function needs to be removed
1933         function getter(obj, path, bindFnToScope) {
1934           if (!path) return obj;
1935           var keys = path.split('.');
1936           var key;
1937           var lastInstance = obj;
1938           var len = keys.length;
1939
1940           for (var i = 0; i < len; i++) {
1941             key = keys[i];
1942             if (obj) {
1943               obj = (lastInstance = obj)[key];
1944             }
1945           }
1946           if (!bindFnToScope && isFunction(obj)) {
1947             return bind(lastInstance, obj);
1948           }
1949           return obj;
1950         }
1951
1952         /**
1953          * Return the DOM siblings between the first and last node in the given array.
1954          * @param {Array} array like object
1955          * @returns {Array} the inputted object or a jqLite collection containing the nodes
1956          */
1957         function getBlockNodes(nodes) {
1958           // TODO(perf): update `nodes` instead of creating a new object?
1959           var node = nodes[0];
1960           var endNode = nodes[nodes.length - 1];
1961           var blockNodes;
1962
1963           for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
1964             if (blockNodes || nodes[i] !== node) {
1965               if (!blockNodes) {
1966                 blockNodes = jqLite(slice.call(nodes, 0, i));
1967               }
1968               blockNodes.push(node);
1969             }
1970           }
1971
1972           return blockNodes || nodes;
1973         }
1974
1975
1976         /**
1977          * Creates a new object without a prototype. This object is useful for lookup without having to
1978          * guard against prototypically inherited properties via hasOwnProperty.
1979          *
1980          * Related micro-benchmarks:
1981          * - http://jsperf.com/object-create2
1982          * - http://jsperf.com/proto-map-lookup/2
1983          * - http://jsperf.com/for-in-vs-object-keys2
1984          *
1985          * @returns {Object}
1986          */
1987         function createMap() {
1988           return Object.create(null);
1989         }
1990
1991         var NODE_TYPE_ELEMENT = 1;
1992         var NODE_TYPE_ATTRIBUTE = 2;
1993         var NODE_TYPE_TEXT = 3;
1994         var NODE_TYPE_COMMENT = 8;
1995         var NODE_TYPE_DOCUMENT = 9;
1996         var NODE_TYPE_DOCUMENT_FRAGMENT = 11;
1997
1998         /**
1999          * @ngdoc type
2000          * @name angular.Module
2001          * @module ng
2002          * @description
2003          *
2004          * Interface for configuring angular {@link angular.module modules}.
2005          */
2006
2007         function setupModuleLoader(window) {
2008
2009           var $injectorMinErr = minErr('$injector');
2010           var ngMinErr = minErr('ng');
2011
2012           function ensure(obj, name, factory) {
2013             return obj[name] || (obj[name] = factory());
2014           }
2015
2016           var angular = ensure(window, 'angular', Object);
2017
2018           // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
2019           angular.$$minErr = angular.$$minErr || minErr;
2020
2021           return ensure(angular, 'module', function() {
2022             /** @type {Object.<string, angular.Module>} */
2023             var modules = {};
2024
2025             /**
2026              * @ngdoc function
2027              * @name angular.module
2028              * @module ng
2029              * @description
2030              *
2031              * The `angular.module` is a global place for creating, registering and retrieving Angular
2032              * modules.
2033              * All modules (angular core or 3rd party) that should be available to an application must be
2034              * registered using this mechanism.
2035              *
2036              * Passing one argument retrieves an existing {@link angular.Module},
2037              * whereas passing more than one argument creates a new {@link angular.Module}
2038              *
2039              *
2040              * # Module
2041              *
2042              * A module is a collection of services, directives, controllers, filters, and configuration information.
2043              * `angular.module` is used to configure the {@link auto.$injector $injector}.
2044              *
2045              * ```js
2046              * // Create a new module
2047              * var myModule = angular.module('myModule', []);
2048              *
2049              * // register a new service
2050              * myModule.value('appName', 'MyCoolApp');
2051              *
2052              * // configure existing services inside initialization blocks.
2053              * myModule.config(['$locationProvider', function($locationProvider) {
2054              *   // Configure existing providers
2055              *   $locationProvider.hashPrefix('!');
2056              * }]);
2057              * ```
2058              *
2059              * Then you can create an injector and load your modules like this:
2060              *
2061              * ```js
2062              * var injector = angular.injector(['ng', 'myModule'])
2063              * ```
2064              *
2065              * However it's more likely that you'll just use
2066              * {@link ng.directive:ngApp ngApp} or
2067              * {@link angular.bootstrap} to simplify this process for you.
2068              *
2069              * @param {!string} name The name of the module to create or retrieve.
2070              * @param {!Array.<string>=} requires If specified then new module is being created. If
2071              *        unspecified then the module is being retrieved for further configuration.
2072              * @param {Function=} configFn Optional configuration function for the module. Same as
2073              *        {@link angular.Module#config Module#config()}.
2074              * @returns {module} new module with the {@link angular.Module} api.
2075              */
2076             return function module(name, requires, configFn) {
2077               var assertNotHasOwnProperty = function(name, context) {
2078                 if (name === 'hasOwnProperty') {
2079                   throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
2080                 }
2081               };
2082
2083               assertNotHasOwnProperty(name, 'module');
2084               if (requires && modules.hasOwnProperty(name)) {
2085                 modules[name] = null;
2086               }
2087               return ensure(modules, name, function() {
2088                 if (!requires) {
2089                   throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
2090                      "the module name or forgot to load it. If registering a module ensure that you " +
2091                      "specify the dependencies as the second argument.", name);
2092                 }
2093
2094                 /** @type {!Array.<Array.<*>>} */
2095                 var invokeQueue = [];
2096
2097                 /** @type {!Array.<Function>} */
2098                 var configBlocks = [];
2099
2100                 /** @type {!Array.<Function>} */
2101                 var runBlocks = [];
2102
2103                 var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
2104
2105                 /** @type {angular.Module} */
2106                 var moduleInstance = {
2107                   // Private state
2108                   _invokeQueue: invokeQueue,
2109                   _configBlocks: configBlocks,
2110                   _runBlocks: runBlocks,
2111
2112                   /**
2113                    * @ngdoc property
2114                    * @name angular.Module#requires
2115                    * @module ng
2116                    *
2117                    * @description
2118                    * Holds the list of modules which the injector will load before the current module is
2119                    * loaded.
2120                    */
2121                   requires: requires,
2122
2123                   /**
2124                    * @ngdoc property
2125                    * @name angular.Module#name
2126                    * @module ng
2127                    *
2128                    * @description
2129                    * Name of the module.
2130                    */
2131                   name: name,
2132
2133
2134                   /**
2135                    * @ngdoc method
2136                    * @name angular.Module#provider
2137                    * @module ng
2138                    * @param {string} name service name
2139                    * @param {Function} providerType Construction function for creating new instance of the
2140                    *                                service.
2141                    * @description
2142                    * See {@link auto.$provide#provider $provide.provider()}.
2143                    */
2144                   provider: invokeLaterAndSetModuleName('$provide', 'provider'),
2145
2146                   /**
2147                    * @ngdoc method
2148                    * @name angular.Module#factory
2149                    * @module ng
2150                    * @param {string} name service name
2151                    * @param {Function} providerFunction Function for creating new instance of the service.
2152                    * @description
2153                    * See {@link auto.$provide#factory $provide.factory()}.
2154                    */
2155                   factory: invokeLaterAndSetModuleName('$provide', 'factory'),
2156
2157                   /**
2158                    * @ngdoc method
2159                    * @name angular.Module#service
2160                    * @module ng
2161                    * @param {string} name service name
2162                    * @param {Function} constructor A constructor function that will be instantiated.
2163                    * @description
2164                    * See {@link auto.$provide#service $provide.service()}.
2165                    */
2166                   service: invokeLaterAndSetModuleName('$provide', 'service'),
2167
2168                   /**
2169                    * @ngdoc method
2170                    * @name angular.Module#value
2171                    * @module ng
2172                    * @param {string} name service name
2173                    * @param {*} object Service instance object.
2174                    * @description
2175                    * See {@link auto.$provide#value $provide.value()}.
2176                    */
2177                   value: invokeLater('$provide', 'value'),
2178
2179                   /**
2180                    * @ngdoc method
2181                    * @name angular.Module#constant
2182                    * @module ng
2183                    * @param {string} name constant name
2184                    * @param {*} object Constant value.
2185                    * @description
2186                    * Because the constants are fixed, they get applied before other provide methods.
2187                    * See {@link auto.$provide#constant $provide.constant()}.
2188                    */
2189                   constant: invokeLater('$provide', 'constant', 'unshift'),
2190
2191                    /**
2192                    * @ngdoc method
2193                    * @name angular.Module#decorator
2194                    * @module ng
2195                    * @param {string} The name of the service to decorate.
2196                    * @param {Function} This function will be invoked when the service needs to be
2197                    *                                    instantiated and should return the decorated service instance.
2198                    * @description
2199                    * See {@link auto.$provide#decorator $provide.decorator()}.
2200                    */
2201                   decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
2202
2203                   /**
2204                    * @ngdoc method
2205                    * @name angular.Module#animation
2206                    * @module ng
2207                    * @param {string} name animation name
2208                    * @param {Function} animationFactory Factory function for creating new instance of an
2209                    *                                    animation.
2210                    * @description
2211                    *
2212                    * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
2213                    *
2214                    *
2215                    * Defines an animation hook that can be later used with
2216                    * {@link $animate $animate} service and directives that use this service.
2217                    *
2218                    * ```js
2219                    * module.animation('.animation-name', function($inject1, $inject2) {
2220                    *   return {
2221                    *     eventName : function(element, done) {
2222                    *       //code to run the animation
2223                    *       //once complete, then run done()
2224                    *       return function cancellationFunction(element) {
2225                    *         //code to cancel the animation
2226                    *       }
2227                    *     }
2228                    *   }
2229                    * })
2230                    * ```
2231                    *
2232                    * See {@link ng.$animateProvider#register $animateProvider.register()} and
2233                    * {@link ngAnimate ngAnimate module} for more information.
2234                    */
2235                   animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
2236
2237                   /**
2238                    * @ngdoc method
2239                    * @name angular.Module#filter
2240                    * @module ng
2241                    * @param {string} name Filter name - this must be a valid angular expression identifier
2242                    * @param {Function} filterFactory Factory function for creating new instance of filter.
2243                    * @description
2244                    * See {@link ng.$filterProvider#register $filterProvider.register()}.
2245                    *
2246                    * <div class="alert alert-warning">
2247                    * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
2248                    * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
2249                    * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
2250                    * (`myapp_subsection_filterx`).
2251                    * </div>
2252                    */
2253                   filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
2254
2255                   /**
2256                    * @ngdoc method
2257                    * @name angular.Module#controller
2258                    * @module ng
2259                    * @param {string|Object} name Controller name, or an object map of controllers where the
2260                    *    keys are the names and the values are the constructors.
2261                    * @param {Function} constructor Controller constructor function.
2262                    * @description
2263                    * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
2264                    */
2265                   controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
2266
2267                   /**
2268                    * @ngdoc method
2269                    * @name angular.Module#directive
2270                    * @module ng
2271                    * @param {string|Object} name Directive name, or an object map of directives where the
2272                    *    keys are the names and the values are the factories.
2273                    * @param {Function} directiveFactory Factory function for creating new instance of
2274                    * directives.
2275                    * @description
2276                    * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
2277                    */
2278                   directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
2279
2280                   /**
2281                    * @ngdoc method
2282                    * @name angular.Module#config
2283                    * @module ng
2284                    * @param {Function} configFn Execute this function on module load. Useful for service
2285                    *    configuration.
2286                    * @description
2287                    * Use this method to register work which needs to be performed on module loading.
2288                    * For more about how to configure services, see
2289                    * {@link providers#provider-recipe Provider Recipe}.
2290                    */
2291                   config: config,
2292
2293                   /**
2294                    * @ngdoc method
2295                    * @name angular.Module#run
2296                    * @module ng
2297                    * @param {Function} initializationFn Execute this function after injector creation.
2298                    *    Useful for application initialization.
2299                    * @description
2300                    * Use this method to register work which should be performed when the injector is done
2301                    * loading all modules.
2302                    */
2303                   run: function(block) {
2304                     runBlocks.push(block);
2305                     return this;
2306                   }
2307                 };
2308
2309                 if (configFn) {
2310                   config(configFn);
2311                 }
2312
2313                 return moduleInstance;
2314
2315                 /**
2316                  * @param {string} provider
2317                  * @param {string} method
2318                  * @param {String=} insertMethod
2319                  * @returns {angular.Module}
2320                  */
2321                 function invokeLater(provider, method, insertMethod, queue) {
2322                   if (!queue) queue = invokeQueue;
2323                   return function() {
2324                     queue[insertMethod || 'push']([provider, method, arguments]);
2325                     return moduleInstance;
2326                   };
2327                 }
2328
2329                 /**
2330                  * @param {string} provider
2331                  * @param {string} method
2332                  * @returns {angular.Module}
2333                  */
2334                 function invokeLaterAndSetModuleName(provider, method) {
2335                   return function(recipeName, factoryFunction) {
2336                     if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
2337                     invokeQueue.push([provider, method, arguments]);
2338                     return moduleInstance;
2339                   };
2340                 }
2341               });
2342             };
2343           });
2344
2345         }
2346
2347         /* global: toDebugString: true */
2348
2349         function serializeObject(obj) {
2350           var seen = [];
2351
2352           return JSON.stringify(obj, function(key, val) {
2353             val = toJsonReplacer(key, val);
2354             if (isObject(val)) {
2355
2356               if (seen.indexOf(val) >= 0) return '...';
2357
2358               seen.push(val);
2359             }
2360             return val;
2361           });
2362         }
2363
2364         function toDebugString(obj) {
2365           if (typeof obj === 'function') {
2366             return obj.toString().replace(/ \{[\s\S]*$/, '');
2367           } else if (isUndefined(obj)) {
2368             return 'undefined';
2369           } else if (typeof obj !== 'string') {
2370             return serializeObject(obj);
2371           }
2372           return obj;
2373         }
2374
2375         /* global angularModule: true,
2376           version: true,
2377
2378           $CompileProvider,
2379
2380           htmlAnchorDirective,
2381           inputDirective,
2382           inputDirective,
2383           formDirective,
2384           scriptDirective,
2385           selectDirective,
2386           styleDirective,
2387           optionDirective,
2388           ngBindDirective,
2389           ngBindHtmlDirective,
2390           ngBindTemplateDirective,
2391           ngClassDirective,
2392           ngClassEvenDirective,
2393           ngClassOddDirective,
2394           ngCloakDirective,
2395           ngControllerDirective,
2396           ngFormDirective,
2397           ngHideDirective,
2398           ngIfDirective,
2399           ngIncludeDirective,
2400           ngIncludeFillContentDirective,
2401           ngInitDirective,
2402           ngNonBindableDirective,
2403           ngPluralizeDirective,
2404           ngRepeatDirective,
2405           ngShowDirective,
2406           ngStyleDirective,
2407           ngSwitchDirective,
2408           ngSwitchWhenDirective,
2409           ngSwitchDefaultDirective,
2410           ngOptionsDirective,
2411           ngTranscludeDirective,
2412           ngModelDirective,
2413           ngListDirective,
2414           ngChangeDirective,
2415           patternDirective,
2416           patternDirective,
2417           requiredDirective,
2418           requiredDirective,
2419           minlengthDirective,
2420           minlengthDirective,
2421           maxlengthDirective,
2422           maxlengthDirective,
2423           ngValueDirective,
2424           ngModelOptionsDirective,
2425           ngAttributeAliasDirectives,
2426           ngEventDirectives,
2427
2428           $AnchorScrollProvider,
2429           $AnimateProvider,
2430           $CoreAnimateCssProvider,
2431           $$CoreAnimateQueueProvider,
2432           $$CoreAnimateRunnerProvider,
2433           $BrowserProvider,
2434           $CacheFactoryProvider,
2435           $ControllerProvider,
2436           $DocumentProvider,
2437           $ExceptionHandlerProvider,
2438           $FilterProvider,
2439           $$ForceReflowProvider,
2440           $InterpolateProvider,
2441           $IntervalProvider,
2442           $$HashMapProvider,
2443           $HttpProvider,
2444           $HttpParamSerializerProvider,
2445           $HttpParamSerializerJQLikeProvider,
2446           $HttpBackendProvider,
2447           $xhrFactoryProvider,
2448           $LocationProvider,
2449           $LogProvider,
2450           $ParseProvider,
2451           $RootScopeProvider,
2452           $QProvider,
2453           $$QProvider,
2454           $$SanitizeUriProvider,
2455           $SceProvider,
2456           $SceDelegateProvider,
2457           $SnifferProvider,
2458           $TemplateCacheProvider,
2459           $TemplateRequestProvider,
2460           $$TestabilityProvider,
2461           $TimeoutProvider,
2462           $$RAFProvider,
2463           $WindowProvider,
2464           $$jqLiteProvider,
2465           $$CookieReaderProvider
2466         */
2467
2468
2469         /**
2470          * @ngdoc object
2471          * @name angular.version
2472          * @module ng
2473          * @description
2474          * An object that contains information about the current AngularJS version.
2475          *
2476          * This object has the following properties:
2477          *
2478          * - `full` – `{string}` – Full version string, such as "0.9.18".
2479          * - `major` – `{number}` – Major version number, such as "0".
2480          * - `minor` – `{number}` – Minor version number, such as "9".
2481          * - `dot` – `{number}` – Dot version number, such as "18".
2482          * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2483          */
2484         var version = {
2485           full: '1.4.8',    // all of these placeholder strings will be replaced by grunt's
2486           major: 1,    // package task
2487           minor: 4,
2488           dot: 8,
2489           codeName: 'ice-manipulation'
2490         };
2491
2492
2493         function publishExternalAPI(angular) {
2494           extend(angular, {
2495             'bootstrap': bootstrap,
2496             'copy': copy,
2497             'extend': extend,
2498             'merge': merge,
2499             'equals': equals,
2500             'element': jqLite,
2501             'forEach': forEach,
2502             'injector': createInjector,
2503             'noop': noop,
2504             'bind': bind,
2505             'toJson': toJson,
2506             'fromJson': fromJson,
2507             'identity': identity,
2508             'isUndefined': isUndefined,
2509             'isDefined': isDefined,
2510             'isString': isString,
2511             'isFunction': isFunction,
2512             'isObject': isObject,
2513             'isNumber': isNumber,
2514             'isElement': isElement,
2515             'isArray': isArray,
2516             'version': version,
2517             'isDate': isDate,
2518             'lowercase': lowercase,
2519             'uppercase': uppercase,
2520             'callbacks': {counter: 0},
2521             'getTestability': getTestability,
2522             '$$minErr': minErr,
2523             '$$csp': csp,
2524             'reloadWithDebugInfo': reloadWithDebugInfo
2525           });
2526
2527           angularModule = setupModuleLoader(window);
2528
2529           angularModule('ng', ['ngLocale'], ['$provide',
2530             function ngModule($provide) {
2531               // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
2532               $provide.provider({
2533                 $$sanitizeUri: $$SanitizeUriProvider
2534               });
2535               $provide.provider('$compile', $CompileProvider).
2536                 directive({
2537                     a: htmlAnchorDirective,
2538                     input: inputDirective,
2539                     textarea: inputDirective,
2540                     form: formDirective,
2541                     script: scriptDirective,
2542                     select: selectDirective,
2543                     style: styleDirective,
2544                     option: optionDirective,
2545                     ngBind: ngBindDirective,
2546                     ngBindHtml: ngBindHtmlDirective,
2547                     ngBindTemplate: ngBindTemplateDirective,
2548                     ngClass: ngClassDirective,
2549                     ngClassEven: ngClassEvenDirective,
2550                     ngClassOdd: ngClassOddDirective,
2551                     ngCloak: ngCloakDirective,
2552                     ngController: ngControllerDirective,
2553                     ngForm: ngFormDirective,
2554                     ngHide: ngHideDirective,
2555                     ngIf: ngIfDirective,
2556                     ngInclude: ngIncludeDirective,
2557                     ngInit: ngInitDirective,
2558                     ngNonBindable: ngNonBindableDirective,
2559                     ngPluralize: ngPluralizeDirective,
2560                     ngRepeat: ngRepeatDirective,
2561                     ngShow: ngShowDirective,
2562                     ngStyle: ngStyleDirective,
2563                     ngSwitch: ngSwitchDirective,
2564                     ngSwitchWhen: ngSwitchWhenDirective,
2565                     ngSwitchDefault: ngSwitchDefaultDirective,
2566                     ngOptions: ngOptionsDirective,
2567                     ngTransclude: ngTranscludeDirective,
2568                     ngModel: ngModelDirective,
2569                     ngList: ngListDirective,
2570                     ngChange: ngChangeDirective,
2571                     pattern: patternDirective,
2572                     ngPattern: patternDirective,
2573                     required: requiredDirective,
2574                     ngRequired: requiredDirective,
2575                     minlength: minlengthDirective,
2576                     ngMinlength: minlengthDirective,
2577                     maxlength: maxlengthDirective,
2578                     ngMaxlength: maxlengthDirective,
2579                     ngValue: ngValueDirective,
2580                     ngModelOptions: ngModelOptionsDirective
2581                 }).
2582                 directive({
2583                   ngInclude: ngIncludeFillContentDirective
2584                 }).
2585                 directive(ngAttributeAliasDirectives).
2586                 directive(ngEventDirectives);
2587               $provide.provider({
2588                 $anchorScroll: $AnchorScrollProvider,
2589                 $animate: $AnimateProvider,
2590                 $animateCss: $CoreAnimateCssProvider,
2591                 $$animateQueue: $$CoreAnimateQueueProvider,
2592                 $$AnimateRunner: $$CoreAnimateRunnerProvider,
2593                 $browser: $BrowserProvider,
2594                 $cacheFactory: $CacheFactoryProvider,
2595                 $controller: $ControllerProvider,
2596                 $document: $DocumentProvider,
2597                 $exceptionHandler: $ExceptionHandlerProvider,
2598                 $filter: $FilterProvider,
2599                 $$forceReflow: $$ForceReflowProvider,
2600                 $interpolate: $InterpolateProvider,
2601                 $interval: $IntervalProvider,
2602                 $http: $HttpProvider,
2603                 $httpParamSerializer: $HttpParamSerializerProvider,
2604                 $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
2605                 $httpBackend: $HttpBackendProvider,
2606                 $xhrFactory: $xhrFactoryProvider,
2607                 $location: $LocationProvider,
2608                 $log: $LogProvider,
2609                 $parse: $ParseProvider,
2610                 $rootScope: $RootScopeProvider,
2611                 $q: $QProvider,
2612                 $$q: $$QProvider,
2613                 $sce: $SceProvider,
2614                 $sceDelegate: $SceDelegateProvider,
2615                 $sniffer: $SnifferProvider,
2616                 $templateCache: $TemplateCacheProvider,
2617                 $templateRequest: $TemplateRequestProvider,
2618                 $$testability: $$TestabilityProvider,
2619                 $timeout: $TimeoutProvider,
2620                 $window: $WindowProvider,
2621                 $$rAF: $$RAFProvider,
2622                 $$jqLite: $$jqLiteProvider,
2623                 $$HashMap: $$HashMapProvider,
2624                 $$cookieReader: $$CookieReaderProvider
2625               });
2626             }
2627           ]);
2628         }
2629
2630         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2631          *     Any commits to this file should be reviewed with security in mind.  *
2632          *   Changes to this file can potentially create security vulnerabilities. *
2633          *          An approval from 2 Core members with history of modifying      *
2634          *                         this file is required.                          *
2635          *                                                                         *
2636          *  Does the change somehow allow for arbitrary javascript to be executed? *
2637          *    Or allows for someone to change the prototype of built-in objects?   *
2638          *     Or gives undesired access to variables likes document or window?    *
2639          * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2640
2641         /* global JQLitePrototype: true,
2642           addEventListenerFn: true,
2643           removeEventListenerFn: true,
2644           BOOLEAN_ATTR: true,
2645           ALIASED_ATTR: true,
2646         */
2647
2648         //////////////////////////////////
2649         //JQLite
2650         //////////////////////////////////
2651
2652         /**
2653          * @ngdoc function
2654          * @name angular.element
2655          * @module ng
2656          * @kind function
2657          *
2658          * @description
2659          * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
2660          *
2661          * If jQuery is available, `angular.element` is an alias for the
2662          * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
2663          * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
2664          *
2665          * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
2666          * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
2667          * commonly needed functionality with the goal of having a very small footprint.</div>
2668          *
2669          * To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
2670          *
2671          * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
2672          * jqLite; they are never raw DOM references.</div>
2673          *
2674          * ## Angular's jqLite
2675          * jqLite provides only the following jQuery methods:
2676          *
2677          * - [`addClass()`](http://api.jquery.com/addClass/)
2678          * - [`after()`](http://api.jquery.com/after/)
2679          * - [`append()`](http://api.jquery.com/append/)
2680          * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
2681          * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
2682          * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
2683          * - [`clone()`](http://api.jquery.com/clone/)
2684          * - [`contents()`](http://api.jquery.com/contents/)
2685          * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
2686          * - [`data()`](http://api.jquery.com/data/)
2687          * - [`detach()`](http://api.jquery.com/detach/)
2688          * - [`empty()`](http://api.jquery.com/empty/)
2689          * - [`eq()`](http://api.jquery.com/eq/)
2690          * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
2691          * - [`hasClass()`](http://api.jquery.com/hasClass/)
2692          * - [`html()`](http://api.jquery.com/html/)
2693          * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
2694          * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
2695          * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
2696          * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
2697          * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
2698          * - [`prepend()`](http://api.jquery.com/prepend/)
2699          * - [`prop()`](http://api.jquery.com/prop/)
2700          * - [`ready()`](http://api.jquery.com/ready/)
2701          * - [`remove()`](http://api.jquery.com/remove/)
2702          * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
2703          * - [`removeClass()`](http://api.jquery.com/removeClass/)
2704          * - [`removeData()`](http://api.jquery.com/removeData/)
2705          * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
2706          * - [`text()`](http://api.jquery.com/text/)
2707          * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
2708          * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
2709          * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
2710          * - [`val()`](http://api.jquery.com/val/)
2711          * - [`wrap()`](http://api.jquery.com/wrap/)
2712          *
2713          * ## jQuery/jqLite Extras
2714          * Angular also provides the following additional methods and events to both jQuery and jqLite:
2715          *
2716          * ### Events
2717          * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
2718          *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM
2719          *    element before it is removed.
2720          *
2721          * ### Methods
2722          * - `controller(name)` - retrieves the controller of the current element or its parent. By default
2723          *   retrieves controller associated with the `ngController` directive. If `name` is provided as
2724          *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
2725          *   `'ngModel'`).
2726          * - `injector()` - retrieves the injector of the current element or its parent.
2727          * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
2728          *   element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
2729          *   be enabled.
2730          * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
2731          *   current element. This getter should be used only on elements that contain a directive which starts a new isolate
2732          *   scope. Calling `scope()` on this element always returns the original non-isolate scope.
2733          *   Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
2734          * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
2735          *   parent element is reached.
2736          *
2737          * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
2738          * @returns {Object} jQuery object.
2739          */
2740
2741         JQLite.expando = 'ng339';
2742
2743         var jqCache = JQLite.cache = {},
2744             jqId = 1,
2745             addEventListenerFn = function(element, type, fn) {
2746               element.addEventListener(type, fn, false);
2747             },
2748             removeEventListenerFn = function(element, type, fn) {
2749               element.removeEventListener(type, fn, false);
2750             };
2751
2752         /*
2753          * !!! This is an undocumented "private" function !!!
2754          */
2755         JQLite._data = function(node) {
2756           //jQuery always returns an object on cache miss
2757           return this.cache[node[this.expando]] || {};
2758         };
2759
2760         function jqNextId() { return ++jqId; }
2761
2762
2763         var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
2764         var MOZ_HACK_REGEXP = /^moz([A-Z])/;
2765         var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
2766         var jqLiteMinErr = minErr('jqLite');
2767
2768         /**
2769          * Converts snake_case to camelCase.
2770          * Also there is special case for Moz prefix starting with upper case letter.
2771          * @param name Name to normalize
2772          */
2773         function camelCase(name) {
2774           return name.
2775             replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
2776               return offset ? letter.toUpperCase() : letter;
2777             }).
2778             replace(MOZ_HACK_REGEXP, 'Moz$1');
2779         }
2780
2781         var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
2782         var HTML_REGEXP = /<|&#?\w+;/;
2783         var TAG_NAME_REGEXP = /<([\w:-]+)/;
2784         var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi;
2785
2786         var wrapMap = {
2787           'option': [1, '<select multiple="multiple">', '</select>'],
2788
2789           'thead': [1, '<table>', '</table>'],
2790           'col': [2, '<table><colgroup>', '</colgroup></table>'],
2791           'tr': [2, '<table><tbody>', '</tbody></table>'],
2792           'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
2793           '_default': [0, "", ""]
2794         };
2795
2796         wrapMap.optgroup = wrapMap.option;
2797         wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
2798         wrapMap.th = wrapMap.td;
2799
2800
2801         function jqLiteIsTextNode(html) {
2802           return !HTML_REGEXP.test(html);
2803         }
2804
2805         function jqLiteAcceptsData(node) {
2806           // The window object can accept data but has no nodeType
2807           // Otherwise we are only interested in elements (1) and documents (9)
2808           var nodeType = node.nodeType;
2809           return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
2810         }
2811
2812         function jqLiteHasData(node) {
2813           for (var key in jqCache[node.ng339]) {
2814             return true;
2815           }
2816           return false;
2817         }
2818
2819         function jqLiteBuildFragment(html, context) {
2820           var tmp, tag, wrap,
2821               fragment = context.createDocumentFragment(),
2822               nodes = [], i;
2823
2824           if (jqLiteIsTextNode(html)) {
2825             // Convert non-html into a text node
2826             nodes.push(context.createTextNode(html));
2827           } else {
2828             // Convert html into DOM nodes
2829             tmp = tmp || fragment.appendChild(context.createElement("div"));
2830             tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
2831             wrap = wrapMap[tag] || wrapMap._default;
2832             tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
2833
2834             // Descend through wrappers to the right content
2835             i = wrap[0];
2836             while (i--) {
2837               tmp = tmp.lastChild;
2838             }
2839
2840             nodes = concat(nodes, tmp.childNodes);
2841
2842             tmp = fragment.firstChild;
2843             tmp.textContent = "";
2844           }
2845
2846           // Remove wrapper from fragment
2847           fragment.textContent = "";
2848           fragment.innerHTML = ""; // Clear inner HTML
2849           forEach(nodes, function(node) {
2850             fragment.appendChild(node);
2851           });
2852
2853           return fragment;
2854         }
2855
2856         function jqLiteParseHTML(html, context) {
2857           context = context || document;
2858           var parsed;
2859
2860           if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
2861             return [context.createElement(parsed[1])];
2862           }
2863
2864           if ((parsed = jqLiteBuildFragment(html, context))) {
2865             return parsed.childNodes;
2866           }
2867
2868           return [];
2869         }
2870
2871
2872         // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
2873         var jqLiteContains = Node.prototype.contains || function(arg) {
2874           // jshint bitwise: false
2875           return !!(this.compareDocumentPosition(arg) & 16);
2876           // jshint bitwise: true
2877         };
2878
2879         /////////////////////////////////////////////
2880         function JQLite(element) {
2881           if (element instanceof JQLite) {
2882             return element;
2883           }
2884
2885           var argIsString;
2886
2887           if (isString(element)) {
2888             element = trim(element);
2889             argIsString = true;
2890           }
2891           if (!(this instanceof JQLite)) {
2892             if (argIsString && element.charAt(0) != '<') {
2893               throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
2894             }
2895             return new JQLite(element);
2896           }
2897
2898           if (argIsString) {
2899             jqLiteAddNodes(this, jqLiteParseHTML(element));
2900           } else {
2901             jqLiteAddNodes(this, element);
2902           }
2903         }
2904
2905         function jqLiteClone(element) {
2906           return element.cloneNode(true);
2907         }
2908
2909         function jqLiteDealoc(element, onlyDescendants) {
2910           if (!onlyDescendants) jqLiteRemoveData(element);
2911
2912           if (element.querySelectorAll) {
2913             var descendants = element.querySelectorAll('*');
2914             for (var i = 0, l = descendants.length; i < l; i++) {
2915               jqLiteRemoveData(descendants[i]);
2916             }
2917           }
2918         }
2919
2920         function jqLiteOff(element, type, fn, unsupported) {
2921           if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
2922
2923           var expandoStore = jqLiteExpandoStore(element);
2924           var events = expandoStore && expandoStore.events;
2925           var handle = expandoStore && expandoStore.handle;
2926
2927           if (!handle) return; //no listeners registered
2928
2929           if (!type) {
2930             for (type in events) {
2931               if (type !== '$destroy') {
2932                 removeEventListenerFn(element, type, handle);
2933               }
2934               delete events[type];
2935             }
2936           } else {
2937
2938             var removeHandler = function(type) {
2939               var listenerFns = events[type];
2940               if (isDefined(fn)) {
2941                 arrayRemove(listenerFns || [], fn);
2942               }
2943               if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
2944                 removeEventListenerFn(element, type, handle);
2945                 delete events[type];
2946               }
2947             };
2948
2949             forEach(type.split(' '), function(type) {
2950               removeHandler(type);
2951               if (MOUSE_EVENT_MAP[type]) {
2952                 removeHandler(MOUSE_EVENT_MAP[type]);
2953               }
2954             });
2955           }
2956         }
2957
2958         function jqLiteRemoveData(element, name) {
2959           var expandoId = element.ng339;
2960           var expandoStore = expandoId && jqCache[expandoId];
2961
2962           if (expandoStore) {
2963             if (name) {
2964               delete expandoStore.data[name];
2965               return;
2966             }
2967
2968             if (expandoStore.handle) {
2969               if (expandoStore.events.$destroy) {
2970                 expandoStore.handle({}, '$destroy');
2971               }
2972               jqLiteOff(element);
2973             }
2974             delete jqCache[expandoId];
2975             element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
2976           }
2977         }
2978
2979
2980         function jqLiteExpandoStore(element, createIfNecessary) {
2981           var expandoId = element.ng339,
2982               expandoStore = expandoId && jqCache[expandoId];
2983
2984           if (createIfNecessary && !expandoStore) {
2985             element.ng339 = expandoId = jqNextId();
2986             expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};
2987           }
2988
2989           return expandoStore;
2990         }
2991
2992
2993         function jqLiteData(element, key, value) {
2994           if (jqLiteAcceptsData(element)) {
2995
2996             var isSimpleSetter = isDefined(value);
2997             var isSimpleGetter = !isSimpleSetter && key && !isObject(key);
2998             var massGetter = !key;
2999             var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);
3000             var data = expandoStore && expandoStore.data;
3001
3002             if (isSimpleSetter) { // data('key', value)
3003               data[key] = value;
3004             } else {
3005               if (massGetter) {  // data()
3006                 return data;
3007               } else {
3008                 if (isSimpleGetter) { // data('key')
3009                   // don't force creation of expandoStore if it doesn't exist yet
3010                   return data && data[key];
3011                 } else { // mass-setter: data({key1: val1, key2: val2})
3012                   extend(data, key);
3013                 }
3014               }
3015             }
3016           }
3017         }
3018
3019         function jqLiteHasClass(element, selector) {
3020           if (!element.getAttribute) return false;
3021           return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
3022               indexOf(" " + selector + " ") > -1);
3023         }
3024
3025         function jqLiteRemoveClass(element, cssClasses) {
3026           if (cssClasses && element.setAttribute) {
3027             forEach(cssClasses.split(' '), function(cssClass) {
3028               element.setAttribute('class', trim(
3029                   (" " + (element.getAttribute('class') || '') + " ")
3030                   .replace(/[\n\t]/g, " ")
3031                   .replace(" " + trim(cssClass) + " ", " "))
3032               );
3033             });
3034           }
3035         }
3036
3037         function jqLiteAddClass(element, cssClasses) {
3038           if (cssClasses && element.setAttribute) {
3039             var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
3040                                     .replace(/[\n\t]/g, " ");
3041
3042             forEach(cssClasses.split(' '), function(cssClass) {
3043               cssClass = trim(cssClass);
3044               if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
3045                 existingClasses += cssClass + ' ';
3046               }
3047             });
3048
3049             element.setAttribute('class', trim(existingClasses));
3050           }
3051         }
3052
3053
3054         function jqLiteAddNodes(root, elements) {
3055           // THIS CODE IS VERY HOT. Don't make changes without benchmarking.
3056
3057           if (elements) {
3058
3059             // if a Node (the most common case)
3060             if (elements.nodeType) {
3061               root[root.length++] = elements;
3062             } else {
3063               var length = elements.length;
3064
3065               // if an Array or NodeList and not a Window
3066               if (typeof length === 'number' && elements.window !== elements) {
3067                 if (length) {
3068                   for (var i = 0; i < length; i++) {
3069                     root[root.length++] = elements[i];
3070                   }
3071                 }
3072               } else {
3073                 root[root.length++] = elements;
3074               }
3075             }
3076           }
3077         }
3078
3079
3080         function jqLiteController(element, name) {
3081           return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
3082         }
3083
3084         function jqLiteInheritedData(element, name, value) {
3085           // if element is the document object work with the html element instead
3086           // this makes $(document).scope() possible
3087           if (element.nodeType == NODE_TYPE_DOCUMENT) {
3088             element = element.documentElement;
3089           }
3090           var names = isArray(name) ? name : [name];
3091
3092           while (element) {
3093             for (var i = 0, ii = names.length; i < ii; i++) {
3094               if (isDefined(value = jqLite.data(element, names[i]))) return value;
3095             }
3096
3097             // If dealing with a document fragment node with a host element, and no parent, use the host
3098             // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
3099             // to lookup parent controllers.
3100             element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);
3101           }
3102         }
3103
3104         function jqLiteEmpty(element) {
3105           jqLiteDealoc(element, true);
3106           while (element.firstChild) {
3107             element.removeChild(element.firstChild);
3108           }
3109         }
3110
3111         function jqLiteRemove(element, keepData) {
3112           if (!keepData) jqLiteDealoc(element);
3113           var parent = element.parentNode;
3114           if (parent) parent.removeChild(element);
3115         }
3116
3117
3118         function jqLiteDocumentLoaded(action, win) {
3119           win = win || window;
3120           if (win.document.readyState === 'complete') {
3121             // Force the action to be run async for consistent behaviour
3122             // from the action's point of view
3123             // i.e. it will definitely not be in a $apply
3124             win.setTimeout(action);
3125           } else {
3126             // No need to unbind this handler as load is only ever called once
3127             jqLite(win).on('load', action);
3128           }
3129         }
3130
3131         //////////////////////////////////////////
3132         // Functions which are declared directly.
3133         //////////////////////////////////////////
3134         var JQLitePrototype = JQLite.prototype = {
3135           ready: function(fn) {
3136             var fired = false;
3137
3138             function trigger() {
3139               if (fired) return;
3140               fired = true;
3141               fn();
3142             }
3143
3144             // check if document is already loaded
3145             if (document.readyState === 'complete') {
3146               setTimeout(trigger);
3147             } else {
3148               this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
3149               // we can not use jqLite since we are not done loading and jQuery could be loaded later.
3150               // jshint -W064
3151               JQLite(window).on('load', trigger); // fallback to window.onload for others
3152               // jshint +W064
3153             }
3154           },
3155           toString: function() {
3156             var value = [];
3157             forEach(this, function(e) { value.push('' + e);});
3158             return '[' + value.join(', ') + ']';
3159           },
3160
3161           eq: function(index) {
3162               return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
3163           },
3164
3165           length: 0,
3166           push: push,
3167           sort: [].sort,
3168           splice: [].splice
3169         };
3170
3171         //////////////////////////////////////////
3172         // Functions iterating getter/setters.
3173         // these functions return self on setter and
3174         // value on get.
3175         //////////////////////////////////////////
3176         var BOOLEAN_ATTR = {};
3177         forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
3178           BOOLEAN_ATTR[lowercase(value)] = value;
3179         });
3180         var BOOLEAN_ELEMENTS = {};
3181         forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
3182           BOOLEAN_ELEMENTS[value] = true;
3183         });
3184         var ALIASED_ATTR = {
3185           'ngMinlength': 'minlength',
3186           'ngMaxlength': 'maxlength',
3187           'ngMin': 'min',
3188           'ngMax': 'max',
3189           'ngPattern': 'pattern'
3190         };
3191
3192         function getBooleanAttrName(element, name) {
3193           // check dom last since we will most likely fail on name
3194           var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
3195
3196           // booleanAttr is here twice to minimize DOM access
3197           return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
3198         }
3199
3200         function getAliasedAttrName(name) {
3201           return ALIASED_ATTR[name];
3202         }
3203
3204         forEach({
3205           data: jqLiteData,
3206           removeData: jqLiteRemoveData,
3207           hasData: jqLiteHasData
3208         }, function(fn, name) {
3209           JQLite[name] = fn;
3210         });
3211
3212         forEach({
3213           data: jqLiteData,
3214           inheritedData: jqLiteInheritedData,
3215
3216           scope: function(element) {
3217             // Can't use jqLiteData here directly so we stay compatible with jQuery!
3218             return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
3219           },
3220
3221           isolateScope: function(element) {
3222             // Can't use jqLiteData here directly so we stay compatible with jQuery!
3223             return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
3224           },
3225
3226           controller: jqLiteController,
3227
3228           injector: function(element) {
3229             return jqLiteInheritedData(element, '$injector');
3230           },
3231
3232           removeAttr: function(element, name) {
3233             element.removeAttribute(name);
3234           },
3235
3236           hasClass: jqLiteHasClass,
3237
3238           css: function(element, name, value) {
3239             name = camelCase(name);
3240
3241             if (isDefined(value)) {
3242               element.style[name] = value;
3243             } else {
3244               return element.style[name];
3245             }
3246           },
3247
3248           attr: function(element, name, value) {
3249             var nodeType = element.nodeType;
3250             if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
3251               return;
3252             }
3253             var lowercasedName = lowercase(name);
3254             if (BOOLEAN_ATTR[lowercasedName]) {
3255               if (isDefined(value)) {
3256                 if (!!value) {
3257                   element[name] = true;
3258                   element.setAttribute(name, lowercasedName);
3259                 } else {
3260                   element[name] = false;
3261                   element.removeAttribute(lowercasedName);
3262                 }
3263               } else {
3264                 return (element[name] ||
3265                          (element.attributes.getNamedItem(name) || noop).specified)
3266                        ? lowercasedName
3267                        : undefined;
3268               }
3269             } else if (isDefined(value)) {
3270               element.setAttribute(name, value);
3271             } else if (element.getAttribute) {
3272               // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
3273               // some elements (e.g. Document) don't have get attribute, so return undefined
3274               var ret = element.getAttribute(name, 2);
3275               // normalize non-existing attributes to undefined (as jQuery)
3276               return ret === null ? undefined : ret;
3277             }
3278           },
3279
3280           prop: function(element, name, value) {
3281             if (isDefined(value)) {
3282               element[name] = value;
3283             } else {
3284               return element[name];
3285             }
3286           },
3287
3288           text: (function() {
3289             getText.$dv = '';
3290             return getText;
3291
3292             function getText(element, value) {
3293               if (isUndefined(value)) {
3294                 var nodeType = element.nodeType;
3295                 return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';
3296               }
3297               element.textContent = value;
3298             }
3299           })(),
3300
3301           val: function(element, value) {
3302             if (isUndefined(value)) {
3303               if (element.multiple && nodeName_(element) === 'select') {
3304                 var result = [];
3305                 forEach(element.options, function(option) {
3306                   if (option.selected) {
3307                     result.push(option.value || option.text);
3308                   }
3309                 });
3310                 return result.length === 0 ? null : result;
3311               }
3312               return element.value;
3313             }
3314             element.value = value;
3315           },
3316
3317           html: function(element, value) {
3318             if (isUndefined(value)) {
3319               return element.innerHTML;
3320             }
3321             jqLiteDealoc(element, true);
3322             element.innerHTML = value;
3323           },
3324
3325           empty: jqLiteEmpty
3326         }, function(fn, name) {
3327           /**
3328            * Properties: writes return selection, reads return first value
3329            */
3330           JQLite.prototype[name] = function(arg1, arg2) {
3331             var i, key;
3332             var nodeCount = this.length;
3333
3334             // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
3335             // in a way that survives minification.
3336             // jqLiteEmpty takes no arguments but is a setter.
3337             if (fn !== jqLiteEmpty &&
3338                 (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
3339               if (isObject(arg1)) {
3340
3341                 // we are a write, but the object properties are the key/values
3342                 for (i = 0; i < nodeCount; i++) {
3343                   if (fn === jqLiteData) {
3344                     // data() takes the whole object in jQuery
3345                     fn(this[i], arg1);
3346                   } else {
3347                     for (key in arg1) {
3348                       fn(this[i], key, arg1[key]);
3349                     }
3350                   }
3351                 }
3352                 // return self for chaining
3353                 return this;
3354               } else {
3355                 // we are a read, so read the first child.
3356                 // TODO: do we still need this?
3357                 var value = fn.$dv;
3358                 // Only if we have $dv do we iterate over all, otherwise it is just the first element.
3359                 var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
3360                 for (var j = 0; j < jj; j++) {
3361                   var nodeValue = fn(this[j], arg1, arg2);
3362                   value = value ? value + nodeValue : nodeValue;
3363                 }
3364                 return value;
3365               }
3366             } else {
3367               // we are a write, so apply to all children
3368               for (i = 0; i < nodeCount; i++) {
3369                 fn(this[i], arg1, arg2);
3370               }
3371               // return self for chaining
3372               return this;
3373             }
3374           };
3375         });
3376
3377         function createEventHandler(element, events) {
3378           var eventHandler = function(event, type) {
3379             // jQuery specific api
3380             event.isDefaultPrevented = function() {
3381               return event.defaultPrevented;
3382             };
3383
3384             var eventFns = events[type || event.type];
3385             var eventFnsLength = eventFns ? eventFns.length : 0;
3386
3387             if (!eventFnsLength) return;
3388
3389             if (isUndefined(event.immediatePropagationStopped)) {
3390               var originalStopImmediatePropagation = event.stopImmediatePropagation;
3391               event.stopImmediatePropagation = function() {
3392                 event.immediatePropagationStopped = true;
3393
3394                 if (event.stopPropagation) {
3395                   event.stopPropagation();
3396                 }
3397
3398                 if (originalStopImmediatePropagation) {
3399                   originalStopImmediatePropagation.call(event);
3400                 }
3401               };
3402             }
3403
3404             event.isImmediatePropagationStopped = function() {
3405               return event.immediatePropagationStopped === true;
3406             };
3407
3408             // Some events have special handlers that wrap the real handler
3409             var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;
3410
3411             // Copy event handlers in case event handlers array is modified during execution.
3412             if ((eventFnsLength > 1)) {
3413               eventFns = shallowCopy(eventFns);
3414             }
3415
3416             for (var i = 0; i < eventFnsLength; i++) {
3417               if (!event.isImmediatePropagationStopped()) {
3418                 handlerWrapper(element, event, eventFns[i]);
3419               }
3420             }
3421           };
3422
3423           // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
3424           //       events on `element`
3425           eventHandler.elem = element;
3426           return eventHandler;
3427         }
3428
3429         function defaultHandlerWrapper(element, event, handler) {
3430           handler.call(element, event);
3431         }
3432
3433         function specialMouseHandlerWrapper(target, event, handler) {
3434           // Refer to jQuery's implementation of mouseenter & mouseleave
3435           // Read about mouseenter and mouseleave:
3436           // http://www.quirksmode.org/js/events_mouse.html#link8
3437           var related = event.relatedTarget;
3438           // For mousenter/leave call the handler if related is outside the target.
3439           // NB: No relatedTarget if the mouse left/entered the browser window
3440           if (!related || (related !== target && !jqLiteContains.call(target, related))) {
3441             handler.call(target, event);
3442           }
3443         }
3444
3445         //////////////////////////////////////////
3446         // Functions iterating traversal.
3447         // These functions chain results into a single
3448         // selector.
3449         //////////////////////////////////////////
3450         forEach({
3451           removeData: jqLiteRemoveData,
3452
3453           on: function jqLiteOn(element, type, fn, unsupported) {
3454             if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
3455
3456             // Do not add event handlers to non-elements because they will not be cleaned up.
3457             if (!jqLiteAcceptsData(element)) {
3458               return;
3459             }
3460
3461             var expandoStore = jqLiteExpandoStore(element, true);
3462             var events = expandoStore.events;
3463             var handle = expandoStore.handle;
3464
3465             if (!handle) {
3466               handle = expandoStore.handle = createEventHandler(element, events);
3467             }
3468
3469             // http://jsperf.com/string-indexof-vs-split
3470             var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
3471             var i = types.length;
3472
3473             var addHandler = function(type, specialHandlerWrapper, noEventListener) {
3474               var eventFns = events[type];
3475
3476               if (!eventFns) {
3477                 eventFns = events[type] = [];
3478                 eventFns.specialHandlerWrapper = specialHandlerWrapper;
3479                 if (type !== '$destroy' && !noEventListener) {
3480                   addEventListenerFn(element, type, handle);
3481                 }
3482               }
3483
3484               eventFns.push(fn);
3485             };
3486
3487             while (i--) {
3488               type = types[i];
3489               if (MOUSE_EVENT_MAP[type]) {
3490                 addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
3491                 addHandler(type, undefined, true);
3492               } else {
3493                 addHandler(type);
3494               }
3495             }
3496           },
3497
3498           off: jqLiteOff,
3499
3500           one: function(element, type, fn) {
3501             element = jqLite(element);
3502
3503             //add the listener twice so that when it is called
3504             //you can remove the original function and still be
3505             //able to call element.off(ev, fn) normally
3506             element.on(type, function onFn() {
3507               element.off(type, fn);
3508               element.off(type, onFn);
3509             });
3510             element.on(type, fn);
3511           },
3512
3513           replaceWith: function(element, replaceNode) {
3514             var index, parent = element.parentNode;
3515             jqLiteDealoc(element);
3516             forEach(new JQLite(replaceNode), function(node) {
3517               if (index) {
3518                 parent.insertBefore(node, index.nextSibling);
3519               } else {
3520                 parent.replaceChild(node, element);
3521               }
3522               index = node;
3523             });
3524           },
3525
3526           children: function(element) {
3527             var children = [];
3528             forEach(element.childNodes, function(element) {
3529               if (element.nodeType === NODE_TYPE_ELEMENT) {
3530                 children.push(element);
3531               }
3532             });
3533             return children;
3534           },
3535
3536           contents: function(element) {
3537             return element.contentDocument || element.childNodes || [];
3538           },
3539
3540           append: function(element, node) {
3541             var nodeType = element.nodeType;
3542             if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
3543
3544             node = new JQLite(node);
3545
3546             for (var i = 0, ii = node.length; i < ii; i++) {
3547               var child = node[i];
3548               element.appendChild(child);
3549             }
3550           },
3551
3552           prepend: function(element, node) {
3553             if (element.nodeType === NODE_TYPE_ELEMENT) {
3554               var index = element.firstChild;
3555               forEach(new JQLite(node), function(child) {
3556                 element.insertBefore(child, index);
3557               });
3558             }
3559           },
3560
3561           wrap: function(element, wrapNode) {
3562             wrapNode = jqLite(wrapNode).eq(0).clone()[0];
3563             var parent = element.parentNode;
3564             if (parent) {
3565               parent.replaceChild(wrapNode, element);
3566             }
3567             wrapNode.appendChild(element);
3568           },
3569
3570           remove: jqLiteRemove,
3571
3572           detach: function(element) {
3573             jqLiteRemove(element, true);
3574           },
3575
3576           after: function(element, newElement) {
3577             var index = element, parent = element.parentNode;
3578             newElement = new JQLite(newElement);
3579
3580             for (var i = 0, ii = newElement.length; i < ii; i++) {
3581               var node = newElement[i];
3582               parent.insertBefore(node, index.nextSibling);
3583               index = node;
3584             }
3585           },
3586
3587           addClass: jqLiteAddClass,
3588           removeClass: jqLiteRemoveClass,
3589
3590           toggleClass: function(element, selector, condition) {
3591             if (selector) {
3592               forEach(selector.split(' '), function(className) {
3593                 var classCondition = condition;
3594                 if (isUndefined(classCondition)) {
3595                   classCondition = !jqLiteHasClass(element, className);
3596                 }
3597                 (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
3598               });
3599             }
3600           },
3601
3602           parent: function(element) {
3603             var parent = element.parentNode;
3604             return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;
3605           },
3606
3607           next: function(element) {
3608             return element.nextElementSibling;
3609           },
3610
3611           find: function(element, selector) {
3612             if (element.getElementsByTagName) {
3613               return element.getElementsByTagName(selector);
3614             } else {
3615               return [];
3616             }
3617           },
3618
3619           clone: jqLiteClone,
3620
3621           triggerHandler: function(element, event, extraParameters) {
3622
3623             var dummyEvent, eventFnsCopy, handlerArgs;
3624             var eventName = event.type || event;
3625             var expandoStore = jqLiteExpandoStore(element);
3626             var events = expandoStore && expandoStore.events;
3627             var eventFns = events && events[eventName];
3628
3629             if (eventFns) {
3630               // Create a dummy event to pass to the handlers
3631               dummyEvent = {
3632                 preventDefault: function() { this.defaultPrevented = true; },
3633                 isDefaultPrevented: function() { return this.defaultPrevented === true; },
3634                 stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
3635                 isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
3636                 stopPropagation: noop,
3637                 type: eventName,
3638                 target: element
3639               };
3640
3641               // If a custom event was provided then extend our dummy event with it
3642               if (event.type) {
3643                 dummyEvent = extend(dummyEvent, event);
3644               }
3645
3646               // Copy event handlers in case event handlers array is modified during execution.
3647               eventFnsCopy = shallowCopy(eventFns);
3648               handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
3649
3650               forEach(eventFnsCopy, function(fn) {
3651                 if (!dummyEvent.isImmediatePropagationStopped()) {
3652                   fn.apply(element, handlerArgs);
3653                 }
3654               });
3655             }
3656           }
3657         }, function(fn, name) {
3658           /**
3659            * chaining functions
3660            */
3661           JQLite.prototype[name] = function(arg1, arg2, arg3) {
3662             var value;
3663
3664             for (var i = 0, ii = this.length; i < ii; i++) {
3665               if (isUndefined(value)) {
3666                 value = fn(this[i], arg1, arg2, arg3);
3667                 if (isDefined(value)) {
3668                   // any function which returns a value needs to be wrapped
3669                   value = jqLite(value);
3670                 }
3671               } else {
3672                 jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
3673               }
3674             }
3675             return isDefined(value) ? value : this;
3676           };
3677
3678           // bind legacy bind/unbind to on/off
3679           JQLite.prototype.bind = JQLite.prototype.on;
3680           JQLite.prototype.unbind = JQLite.prototype.off;
3681         });
3682
3683
3684         // Provider for private $$jqLite service
3685         function $$jqLiteProvider() {
3686           this.$get = function $$jqLite() {
3687             return extend(JQLite, {
3688               hasClass: function(node, classes) {
3689                 if (node.attr) node = node[0];
3690                 return jqLiteHasClass(node, classes);
3691               },
3692               addClass: function(node, classes) {
3693                 if (node.attr) node = node[0];
3694                 return jqLiteAddClass(node, classes);
3695               },
3696               removeClass: function(node, classes) {
3697                 if (node.attr) node = node[0];
3698                 return jqLiteRemoveClass(node, classes);
3699               }
3700             });
3701           };
3702         }
3703
3704         /**
3705          * Computes a hash of an 'obj'.
3706          * Hash of a:
3707          *  string is string
3708          *  number is number as string
3709          *  object is either result of calling $$hashKey function on the object or uniquely generated id,
3710          *         that is also assigned to the $$hashKey property of the object.
3711          *
3712          * @param obj
3713          * @returns {string} hash string such that the same input will have the same hash string.
3714          *         The resulting string key is in 'type:hashKey' format.
3715          */
3716         function hashKey(obj, nextUidFn) {
3717           var key = obj && obj.$$hashKey;
3718
3719           if (key) {
3720             if (typeof key === 'function') {
3721               key = obj.$$hashKey();
3722             }
3723             return key;
3724           }
3725
3726           var objType = typeof obj;
3727           if (objType == 'function' || (objType == 'object' && obj !== null)) {
3728             key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();
3729           } else {
3730             key = objType + ':' + obj;
3731           }
3732
3733           return key;
3734         }
3735
3736         /**
3737          * HashMap which can use objects as keys
3738          */
3739         function HashMap(array, isolatedUid) {
3740           if (isolatedUid) {
3741             var uid = 0;
3742             this.nextUid = function() {
3743               return ++uid;
3744             };
3745           }
3746           forEach(array, this.put, this);
3747         }
3748         HashMap.prototype = {
3749           /**
3750            * Store key value pair
3751            * @param key key to store can be any type
3752            * @param value value to store can be any type
3753            */
3754           put: function(key, value) {
3755             this[hashKey(key, this.nextUid)] = value;
3756           },
3757
3758           /**
3759            * @param key
3760            * @returns {Object} the value for the key
3761            */
3762           get: function(key) {
3763             return this[hashKey(key, this.nextUid)];
3764           },
3765
3766           /**
3767            * Remove the key/value pair
3768            * @param key
3769            */
3770           remove: function(key) {
3771             var value = this[key = hashKey(key, this.nextUid)];
3772             delete this[key];
3773             return value;
3774           }
3775         };
3776
3777         var $$HashMapProvider = [function() {
3778           this.$get = [function() {
3779             return HashMap;
3780           }];
3781         }];
3782
3783         /**
3784          * @ngdoc function
3785          * @module ng
3786          * @name angular.injector
3787          * @kind function
3788          *
3789          * @description
3790          * Creates an injector object that can be used for retrieving services as well as for
3791          * dependency injection (see {@link guide/di dependency injection}).
3792          *
3793          * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
3794          *     {@link angular.module}. The `ng` module must be explicitly added.
3795          * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
3796          *     disallows argument name annotation inference.
3797          * @returns {injector} Injector object. See {@link auto.$injector $injector}.
3798          *
3799          * @example
3800          * Typical usage
3801          * ```js
3802          *   // create an injector
3803          *   var $injector = angular.injector(['ng']);
3804          *
3805          *   // use the injector to kick off your application
3806          *   // use the type inference to auto inject arguments, or use implicit injection
3807          *   $injector.invoke(function($rootScope, $compile, $document) {
3808          *     $compile($document)($rootScope);
3809          *     $rootScope.$digest();
3810          *   });
3811          * ```
3812          *
3813          * Sometimes you want to get access to the injector of a currently running Angular app
3814          * from outside Angular. Perhaps, you want to inject and compile some markup after the
3815          * application has been bootstrapped. You can do this using the extra `injector()` added
3816          * to JQuery/jqLite elements. See {@link angular.element}.
3817          *
3818          * *This is fairly rare but could be the case if a third party library is injecting the
3819          * markup.*
3820          *
3821          * In the following example a new block of HTML containing a `ng-controller`
3822          * directive is added to the end of the document body by JQuery. We then compile and link
3823          * it into the current AngularJS scope.
3824          *
3825          * ```js
3826          * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
3827          * $(document.body).append($div);
3828          *
3829          * angular.element(document).injector().invoke(function($compile) {
3830          *   var scope = angular.element($div).scope();
3831          *   $compile($div)(scope);
3832          * });
3833          * ```
3834          */
3835
3836
3837         /**
3838          * @ngdoc module
3839          * @name auto
3840          * @description
3841          *
3842          * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
3843          */
3844
3845         var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
3846         var FN_ARG_SPLIT = /,/;
3847         var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
3848         var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
3849         var $injectorMinErr = minErr('$injector');
3850
3851         function anonFn(fn) {
3852           // For anonymous functions, showing at the very least the function signature can help in
3853           // debugging.
3854           var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
3855               args = fnText.match(FN_ARGS);
3856           if (args) {
3857             return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
3858           }
3859           return 'fn';
3860         }
3861
3862         function annotate(fn, strictDi, name) {
3863           var $inject,
3864               fnText,
3865               argDecl,
3866               last;
3867
3868           if (typeof fn === 'function') {
3869             if (!($inject = fn.$inject)) {
3870               $inject = [];
3871               if (fn.length) {
3872                 if (strictDi) {
3873                   if (!isString(name) || !name) {
3874                     name = fn.name || anonFn(fn);
3875                   }
3876                   throw $injectorMinErr('strictdi',
3877                     '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
3878                 }
3879                 fnText = fn.toString().replace(STRIP_COMMENTS, '');
3880                 argDecl = fnText.match(FN_ARGS);
3881                 forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
3882                   arg.replace(FN_ARG, function(all, underscore, name) {
3883                     $inject.push(name);
3884                   });
3885                 });
3886               }
3887               fn.$inject = $inject;
3888             }
3889           } else if (isArray(fn)) {
3890             last = fn.length - 1;
3891             assertArgFn(fn[last], 'fn');
3892             $inject = fn.slice(0, last);
3893           } else {
3894             assertArgFn(fn, 'fn', true);
3895           }
3896           return $inject;
3897         }
3898
3899         ///////////////////////////////////////
3900
3901         /**
3902          * @ngdoc service
3903          * @name $injector
3904          *
3905          * @description
3906          *
3907          * `$injector` is used to retrieve object instances as defined by
3908          * {@link auto.$provide provider}, instantiate types, invoke methods,
3909          * and load modules.
3910          *
3911          * The following always holds true:
3912          *
3913          * ```js
3914          *   var $injector = angular.injector();
3915          *   expect($injector.get('$injector')).toBe($injector);
3916          *   expect($injector.invoke(function($injector) {
3917          *     return $injector;
3918          *   })).toBe($injector);
3919          * ```
3920          *
3921          * # Injection Function Annotation
3922          *
3923          * JavaScript does not have annotations, and annotations are needed for dependency injection. The
3924          * following are all valid ways of annotating function with injection arguments and are equivalent.
3925          *
3926          * ```js
3927          *   // inferred (only works if code not minified/obfuscated)
3928          *   $injector.invoke(function(serviceA){});
3929          *
3930          *   // annotated
3931          *   function explicit(serviceA) {};
3932          *   explicit.$inject = ['serviceA'];
3933          *   $injector.invoke(explicit);
3934          *
3935          *   // inline
3936          *   $injector.invoke(['serviceA', function(serviceA){}]);
3937          * ```
3938          *
3939          * ## Inference
3940          *
3941          * In JavaScript calling `toString()` on a function returns the function definition. The definition
3942          * can then be parsed and the function arguments can be extracted. This method of discovering
3943          * annotations is disallowed when the injector is in strict mode.
3944          * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
3945          * argument names.
3946          *
3947          * ## `$inject` Annotation
3948          * By adding an `$inject` property onto a function the injection parameters can be specified.
3949          *
3950          * ## Inline
3951          * As an array of injection names, where the last item in the array is the function to call.
3952          */
3953
3954         /**
3955          * @ngdoc method
3956          * @name $injector#get
3957          *
3958          * @description
3959          * Return an instance of the service.
3960          *
3961          * @param {string} name The name of the instance to retrieve.
3962          * @param {string=} caller An optional string to provide the origin of the function call for error messages.
3963          * @return {*} The instance.
3964          */
3965
3966         /**
3967          * @ngdoc method
3968          * @name $injector#invoke
3969          *
3970          * @description
3971          * Invoke the method and supply the method arguments from the `$injector`.
3972          *
3973          * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
3974          *   injected according to the {@link guide/di $inject Annotation} rules.
3975          * @param {Object=} self The `this` for the invoked method.
3976          * @param {Object=} locals Optional object. If preset then any argument names are read from this
3977          *                         object first, before the `$injector` is consulted.
3978          * @returns {*} the value returned by the invoked `fn` function.
3979          */
3980
3981         /**
3982          * @ngdoc method
3983          * @name $injector#has
3984          *
3985          * @description
3986          * Allows the user to query if the particular service exists.
3987          *
3988          * @param {string} name Name of the service to query.
3989          * @returns {boolean} `true` if injector has given service.
3990          */
3991
3992         /**
3993          * @ngdoc method
3994          * @name $injector#instantiate
3995          * @description
3996          * Create a new instance of JS type. The method takes a constructor function, invokes the new
3997          * operator, and supplies all of the arguments to the constructor function as specified by the
3998          * constructor annotation.
3999          *
4000          * @param {Function} Type Annotated constructor function.
4001          * @param {Object=} locals Optional object. If preset then any argument names are read from this
4002          * object first, before the `$injector` is consulted.
4003          * @returns {Object} new instance of `Type`.
4004          */
4005
4006         /**
4007          * @ngdoc method
4008          * @name $injector#annotate
4009          *
4010          * @description
4011          * Returns an array of service names which the function is requesting for injection. This API is
4012          * used by the injector to determine which services need to be injected into the function when the
4013          * function is invoked. There are three ways in which the function can be annotated with the needed
4014          * dependencies.
4015          *
4016          * # Argument names
4017          *
4018          * The simplest form is to extract the dependencies from the arguments of the function. This is done
4019          * by converting the function into a string using `toString()` method and extracting the argument
4020          * names.
4021          * ```js
4022          *   // Given
4023          *   function MyController($scope, $route) {
4024          *     // ...
4025          *   }
4026          *
4027          *   // Then
4028          *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
4029          * ```
4030          *
4031          * You can disallow this method by using strict injection mode.
4032          *
4033          * This method does not work with code minification / obfuscation. For this reason the following
4034          * annotation strategies are supported.
4035          *
4036          * # The `$inject` property
4037          *
4038          * If a function has an `$inject` property and its value is an array of strings, then the strings
4039          * represent names of services to be injected into the function.
4040          * ```js
4041          *   // Given
4042          *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
4043          *     // ...
4044          *   }
4045          *   // Define function dependencies
4046          *   MyController['$inject'] = ['$scope', '$route'];
4047          *
4048          *   // Then
4049          *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
4050          * ```
4051          *
4052          * # The array notation
4053          *
4054          * It is often desirable to inline Injected functions and that's when setting the `$inject` property
4055          * is very inconvenient. In these situations using the array notation to specify the dependencies in
4056          * a way that survives minification is a better choice:
4057          *
4058          * ```js
4059          *   // We wish to write this (not minification / obfuscation safe)
4060          *   injector.invoke(function($compile, $rootScope) {
4061          *     // ...
4062          *   });
4063          *
4064          *   // We are forced to write break inlining
4065          *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
4066          *     // ...
4067          *   };
4068          *   tmpFn.$inject = ['$compile', '$rootScope'];
4069          *   injector.invoke(tmpFn);
4070          *
4071          *   // To better support inline function the inline annotation is supported
4072          *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
4073          *     // ...
4074          *   }]);
4075          *
4076          *   // Therefore
4077          *   expect(injector.annotate(
4078          *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
4079          *    ).toEqual(['$compile', '$rootScope']);
4080          * ```
4081          *
4082          * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
4083          * be retrieved as described above.
4084          *
4085          * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
4086          *
4087          * @returns {Array.<string>} The names of the services which the function requires.
4088          */
4089
4090
4091
4092
4093         /**
4094          * @ngdoc service
4095          * @name $provide
4096          *
4097          * @description
4098          *
4099          * The {@link auto.$provide $provide} service has a number of methods for registering components
4100          * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
4101          * {@link angular.Module}.
4102          *
4103          * An Angular **service** is a singleton object created by a **service factory**.  These **service
4104          * factories** are functions which, in turn, are created by a **service provider**.
4105          * The **service providers** are constructor functions. When instantiated they must contain a
4106          * property called `$get`, which holds the **service factory** function.
4107          *
4108          * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
4109          * correct **service provider**, instantiating it and then calling its `$get` **service factory**
4110          * function to get the instance of the **service**.
4111          *
4112          * Often services have no configuration options and there is no need to add methods to the service
4113          * provider.  The provider will be no more than a constructor function with a `$get` property. For
4114          * these cases the {@link auto.$provide $provide} service has additional helper methods to register
4115          * services without specifying a provider.
4116          *
4117          * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
4118          *     {@link auto.$injector $injector}
4119          * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
4120          *     providers and services.
4121          * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
4122          *     services, not providers.
4123          * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
4124          *     that will be wrapped in a **service provider** object, whose `$get` property will contain the
4125          *     given factory function.
4126          * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
4127          *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate
4128          *      a new object using the given constructor function.
4129          *
4130          * See the individual methods for more information and examples.
4131          */
4132
4133         /**
4134          * @ngdoc method
4135          * @name $provide#provider
4136          * @description
4137          *
4138          * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
4139          * are constructor functions, whose instances are responsible for "providing" a factory for a
4140          * service.
4141          *
4142          * Service provider names start with the name of the service they provide followed by `Provider`.
4143          * For example, the {@link ng.$log $log} service has a provider called
4144          * {@link ng.$logProvider $logProvider}.
4145          *
4146          * Service provider objects can have additional methods which allow configuration of the provider
4147          * and its service. Importantly, you can configure what kind of service is created by the `$get`
4148          * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
4149          * method {@link ng.$logProvider#debugEnabled debugEnabled}
4150          * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
4151          * console or not.
4152          *
4153          * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
4154                                 'Provider'` key.
4155          * @param {(Object|function())} provider If the provider is:
4156          *
4157          *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
4158          *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
4159          *   - `Constructor`: a new instance of the provider will be created using
4160          *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
4161          *
4162          * @returns {Object} registered provider instance
4163
4164          * @example
4165          *
4166          * The following example shows how to create a simple event tracking service and register it using
4167          * {@link auto.$provide#provider $provide.provider()}.
4168          *
4169          * ```js
4170          *  // Define the eventTracker provider
4171          *  function EventTrackerProvider() {
4172          *    var trackingUrl = '/track';
4173          *
4174          *    // A provider method for configuring where the tracked events should been saved
4175          *    this.setTrackingUrl = function(url) {
4176          *      trackingUrl = url;
4177          *    };
4178          *
4179          *    // The service factory function
4180          *    this.$get = ['$http', function($http) {
4181          *      var trackedEvents = {};
4182          *      return {
4183          *        // Call this to track an event
4184          *        event: function(event) {
4185          *          var count = trackedEvents[event] || 0;
4186          *          count += 1;
4187          *          trackedEvents[event] = count;
4188          *          return count;
4189          *        },
4190          *        // Call this to save the tracked events to the trackingUrl
4191          *        save: function() {
4192          *          $http.post(trackingUrl, trackedEvents);
4193          *        }
4194          *      };
4195          *    }];
4196          *  }
4197          *
4198          *  describe('eventTracker', function() {
4199          *    var postSpy;
4200          *
4201          *    beforeEach(module(function($provide) {
4202          *      // Register the eventTracker provider
4203          *      $provide.provider('eventTracker', EventTrackerProvider);
4204          *    }));
4205          *
4206          *    beforeEach(module(function(eventTrackerProvider) {
4207          *      // Configure eventTracker provider
4208          *      eventTrackerProvider.setTrackingUrl('/custom-track');
4209          *    }));
4210          *
4211          *    it('tracks events', inject(function(eventTracker) {
4212          *      expect(eventTracker.event('login')).toEqual(1);
4213          *      expect(eventTracker.event('login')).toEqual(2);
4214          *    }));
4215          *
4216          *    it('saves to the tracking url', inject(function(eventTracker, $http) {
4217          *      postSpy = spyOn($http, 'post');
4218          *      eventTracker.event('login');
4219          *      eventTracker.save();
4220          *      expect(postSpy).toHaveBeenCalled();
4221          *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
4222          *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
4223          *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
4224          *    }));
4225          *  });
4226          * ```
4227          */
4228
4229         /**
4230          * @ngdoc method
4231          * @name $provide#factory
4232          * @description
4233          *
4234          * Register a **service factory**, which will be called to return the service instance.
4235          * This is short for registering a service where its provider consists of only a `$get` property,
4236          * which is the given service factory function.
4237          * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
4238          * configure your service in a provider.
4239          *
4240          * @param {string} name The name of the instance.
4241          * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
4242          *                      Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
4243          * @returns {Object} registered provider instance
4244          *
4245          * @example
4246          * Here is an example of registering a service
4247          * ```js
4248          *   $provide.factory('ping', ['$http', function($http) {
4249          *     return function ping() {
4250          *       return $http.send('/ping');
4251          *     };
4252          *   }]);
4253          * ```
4254          * You would then inject and use this service like this:
4255          * ```js
4256          *   someModule.controller('Ctrl', ['ping', function(ping) {
4257          *     ping();
4258          *   }]);
4259          * ```
4260          */
4261
4262
4263         /**
4264          * @ngdoc method
4265          * @name $provide#service
4266          * @description
4267          *
4268          * Register a **service constructor**, which will be invoked with `new` to create the service
4269          * instance.
4270          * This is short for registering a service where its provider's `$get` property is the service
4271          * constructor function that will be used to instantiate the service instance.
4272          *
4273          * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
4274          * as a type/class.
4275          *
4276          * @param {string} name The name of the instance.
4277          * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
4278          *     that will be instantiated.
4279          * @returns {Object} registered provider instance
4280          *
4281          * @example
4282          * Here is an example of registering a service using
4283          * {@link auto.$provide#service $provide.service(class)}.
4284          * ```js
4285          *   var Ping = function($http) {
4286          *     this.$http = $http;
4287          *   };
4288          *
4289          *   Ping.$inject = ['$http'];
4290          *
4291          *   Ping.prototype.send = function() {
4292          *     return this.$http.get('/ping');
4293          *   };
4294          *   $provide.service('ping', Ping);
4295          * ```
4296          * You would then inject and use this service like this:
4297          * ```js
4298          *   someModule.controller('Ctrl', ['ping', function(ping) {
4299          *     ping.send();
4300          *   }]);
4301          * ```
4302          */
4303
4304
4305         /**
4306          * @ngdoc method
4307          * @name $provide#value
4308          * @description
4309          *
4310          * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
4311          * number, an array, an object or a function.  This is short for registering a service where its
4312          * provider's `$get` property is a factory function that takes no arguments and returns the **value
4313          * service**.
4314          *
4315          * Value services are similar to constant services, except that they cannot be injected into a
4316          * module configuration function (see {@link angular.Module#config}) but they can be overridden by
4317          * an Angular
4318          * {@link auto.$provide#decorator decorator}.
4319          *
4320          * @param {string} name The name of the instance.
4321          * @param {*} value The value.
4322          * @returns {Object} registered provider instance
4323          *
4324          * @example
4325          * Here are some examples of creating value services.
4326          * ```js
4327          *   $provide.value('ADMIN_USER', 'admin');
4328          *
4329          *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
4330          *
4331          *   $provide.value('halfOf', function(value) {
4332          *     return value / 2;
4333          *   });
4334          * ```
4335          */
4336
4337
4338         /**
4339          * @ngdoc method
4340          * @name $provide#constant
4341          * @description
4342          *
4343          * Register a **constant service**, such as a string, a number, an array, an object or a function,
4344          * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
4345          * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
4346          * be overridden by an Angular {@link auto.$provide#decorator decorator}.
4347          *
4348          * @param {string} name The name of the constant.
4349          * @param {*} value The constant value.
4350          * @returns {Object} registered instance
4351          *
4352          * @example
4353          * Here a some examples of creating constants:
4354          * ```js
4355          *   $provide.constant('SHARD_HEIGHT', 306);
4356          *
4357          *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
4358          *
4359          *   $provide.constant('double', function(value) {
4360          *     return value * 2;
4361          *   });
4362          * ```
4363          */
4364
4365
4366         /**
4367          * @ngdoc method
4368          * @name $provide#decorator
4369          * @description
4370          *
4371          * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
4372          * intercepts the creation of a service, allowing it to override or modify the behaviour of the
4373          * service. The object returned by the decorator may be the original service, or a new service
4374          * object which replaces or wraps and delegates to the original service.
4375          *
4376          * @param {string} name The name of the service to decorate.
4377          * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
4378          *    instantiated and should return the decorated service instance. The function is called using
4379          *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
4380          *    Local injection arguments:
4381          *
4382          *    * `$delegate` - The original service instance, which can be monkey patched, configured,
4383          *      decorated or delegated to.
4384          *
4385          * @example
4386          * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
4387          * calls to {@link ng.$log#error $log.warn()}.
4388          * ```js
4389          *   $provide.decorator('$log', ['$delegate', function($delegate) {
4390          *     $delegate.warn = $delegate.error;
4391          *     return $delegate;
4392          *   }]);
4393          * ```
4394          */
4395
4396
4397         function createInjector(modulesToLoad, strictDi) {
4398           strictDi = (strictDi === true);
4399           var INSTANTIATING = {},
4400               providerSuffix = 'Provider',
4401               path = [],
4402               loadedModules = new HashMap([], true),
4403               providerCache = {
4404                 $provide: {
4405                     provider: supportObject(provider),
4406                     factory: supportObject(factory),
4407                     service: supportObject(service),
4408                     value: supportObject(value),
4409                     constant: supportObject(constant),
4410                     decorator: decorator
4411                   }
4412               },
4413               providerInjector = (providerCache.$injector =
4414                   createInternalInjector(providerCache, function(serviceName, caller) {
4415                     if (angular.isString(caller)) {
4416                       path.push(caller);
4417                     }
4418                     throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
4419                   })),
4420               instanceCache = {},
4421               instanceInjector = (instanceCache.$injector =
4422                   createInternalInjector(instanceCache, function(serviceName, caller) {
4423                     var provider = providerInjector.get(serviceName + providerSuffix, caller);
4424                     return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
4425                   }));
4426
4427
4428           forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
4429
4430           return instanceInjector;
4431
4432           ////////////////////////////////////
4433           // $provider
4434           ////////////////////////////////////
4435
4436           function supportObject(delegate) {
4437             return function(key, value) {
4438               if (isObject(key)) {
4439                 forEach(key, reverseParams(delegate));
4440               } else {
4441                 return delegate(key, value);
4442               }
4443             };
4444           }
4445
4446           function provider(name, provider_) {
4447             assertNotHasOwnProperty(name, 'service');
4448             if (isFunction(provider_) || isArray(provider_)) {
4449               provider_ = providerInjector.instantiate(provider_);
4450             }
4451             if (!provider_.$get) {
4452               throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
4453             }
4454             return providerCache[name + providerSuffix] = provider_;
4455           }
4456
4457           function enforceReturnValue(name, factory) {
4458             return function enforcedReturnValue() {
4459               var result = instanceInjector.invoke(factory, this);
4460               if (isUndefined(result)) {
4461                 throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
4462               }
4463               return result;
4464             };
4465           }
4466
4467           function factory(name, factoryFn, enforce) {
4468             return provider(name, {
4469               $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
4470             });
4471           }
4472
4473           function service(name, constructor) {
4474             return factory(name, ['$injector', function($injector) {
4475               return $injector.instantiate(constructor);
4476             }]);
4477           }
4478
4479           function value(name, val) { return factory(name, valueFn(val), false); }
4480
4481           function constant(name, value) {
4482             assertNotHasOwnProperty(name, 'constant');
4483             providerCache[name] = value;
4484             instanceCache[name] = value;
4485           }
4486
4487           function decorator(serviceName, decorFn) {
4488             var origProvider = providerInjector.get(serviceName + providerSuffix),
4489                 orig$get = origProvider.$get;
4490
4491             origProvider.$get = function() {
4492               var origInstance = instanceInjector.invoke(orig$get, origProvider);
4493               return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
4494             };
4495           }
4496
4497           ////////////////////////////////////
4498           // Module Loading
4499           ////////////////////////////////////
4500           function loadModules(modulesToLoad) {
4501             assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');
4502             var runBlocks = [], moduleFn;
4503             forEach(modulesToLoad, function(module) {
4504               if (loadedModules.get(module)) return;
4505               loadedModules.put(module, true);
4506
4507               function runInvokeQueue(queue) {
4508                 var i, ii;
4509                 for (i = 0, ii = queue.length; i < ii; i++) {
4510                   var invokeArgs = queue[i],
4511                       provider = providerInjector.get(invokeArgs[0]);
4512
4513                   provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
4514                 }
4515               }
4516
4517               try {
4518                 if (isString(module)) {
4519                   moduleFn = angularModule(module);
4520                   runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
4521                   runInvokeQueue(moduleFn._invokeQueue);
4522                   runInvokeQueue(moduleFn._configBlocks);
4523                 } else if (isFunction(module)) {
4524                     runBlocks.push(providerInjector.invoke(module));
4525                 } else if (isArray(module)) {
4526                     runBlocks.push(providerInjector.invoke(module));
4527                 } else {
4528                   assertArgFn(module, 'module');
4529                 }
4530               } catch (e) {
4531                 if (isArray(module)) {
4532                   module = module[module.length - 1];
4533                 }
4534                 if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
4535                   // Safari & FF's stack traces don't contain error.message content
4536                   // unlike those of Chrome and IE
4537                   // So if stack doesn't contain message, we create a new string that contains both.
4538                   // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
4539                   /* jshint -W022 */
4540                   e = e.message + '\n' + e.stack;
4541                 }
4542                 throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
4543                           module, e.stack || e.message || e);
4544               }
4545             });
4546             return runBlocks;
4547           }
4548
4549           ////////////////////////////////////
4550           // internal Injector
4551           ////////////////////////////////////
4552
4553           function createInternalInjector(cache, factory) {
4554
4555             function getService(serviceName, caller) {
4556               if (cache.hasOwnProperty(serviceName)) {
4557                 if (cache[serviceName] === INSTANTIATING) {
4558                   throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
4559                             serviceName + ' <- ' + path.join(' <- '));
4560                 }
4561                 return cache[serviceName];
4562               } else {
4563                 try {
4564                   path.unshift(serviceName);
4565                   cache[serviceName] = INSTANTIATING;
4566                   return cache[serviceName] = factory(serviceName, caller);
4567                 } catch (err) {
4568                   if (cache[serviceName] === INSTANTIATING) {
4569                     delete cache[serviceName];
4570                   }
4571                   throw err;
4572                 } finally {
4573                   path.shift();
4574                 }
4575               }
4576             }
4577
4578             function invoke(fn, self, locals, serviceName) {
4579               if (typeof locals === 'string') {
4580                 serviceName = locals;
4581                 locals = null;
4582               }
4583
4584               var args = [],
4585                   $inject = createInjector.$$annotate(fn, strictDi, serviceName),
4586                   length, i,
4587                   key;
4588
4589               for (i = 0, length = $inject.length; i < length; i++) {
4590                 key = $inject[i];
4591                 if (typeof key !== 'string') {
4592                   throw $injectorMinErr('itkn',
4593                           'Incorrect injection token! Expected service name as string, got {0}', key);
4594                 }
4595                 args.push(
4596                   locals && locals.hasOwnProperty(key)
4597                   ? locals[key]
4598                   : getService(key, serviceName)
4599                 );
4600               }
4601               if (isArray(fn)) {
4602                 fn = fn[length];
4603               }
4604
4605               // http://jsperf.com/angularjs-invoke-apply-vs-switch
4606               // #5388
4607               return fn.apply(self, args);
4608             }
4609
4610             function instantiate(Type, locals, serviceName) {
4611               // Check if Type is annotated and use just the given function at n-1 as parameter
4612               // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
4613               // Object creation: http://jsperf.com/create-constructor/2
4614               var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
4615               var returnedValue = invoke(Type, instance, locals, serviceName);
4616
4617               return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
4618             }
4619
4620             return {
4621               invoke: invoke,
4622               instantiate: instantiate,
4623               get: getService,
4624               annotate: createInjector.$$annotate,
4625               has: function(name) {
4626                 return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
4627               }
4628             };
4629           }
4630         }
4631
4632         createInjector.$$annotate = annotate;
4633
4634         /**
4635          * @ngdoc provider
4636          * @name $anchorScrollProvider
4637          *
4638          * @description
4639          * Use `$anchorScrollProvider` to disable automatic scrolling whenever
4640          * {@link ng.$location#hash $location.hash()} changes.
4641          */
4642         function $AnchorScrollProvider() {
4643
4644           var autoScrollingEnabled = true;
4645
4646           /**
4647            * @ngdoc method
4648            * @name $anchorScrollProvider#disableAutoScrolling
4649            *
4650            * @description
4651            * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
4652            * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
4653            * Use this method to disable automatic scrolling.
4654            *
4655            * If automatic scrolling is disabled, one must explicitly call
4656            * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
4657            * current hash.
4658            */
4659           this.disableAutoScrolling = function() {
4660             autoScrollingEnabled = false;
4661           };
4662
4663           /**
4664            * @ngdoc service
4665            * @name $anchorScroll
4666            * @kind function
4667            * @requires $window
4668            * @requires $location
4669            * @requires $rootScope
4670            *
4671            * @description
4672            * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
4673            * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
4674            * in the
4675            * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#the-indicated-part-of-the-document).
4676            *
4677            * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
4678            * match any anchor whenever it changes. This can be disabled by calling
4679            * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
4680            *
4681            * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
4682            * vertical scroll-offset (either fixed or dynamic).
4683            *
4684            * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of
4685            *                       {@link ng.$location#hash $location.hash()} will be used.
4686            *
4687            * @property {(number|function|jqLite)} yOffset
4688            * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
4689            * positioned elements at the top of the page, such as navbars, headers etc.
4690            *
4691            * `yOffset` can be specified in various ways:
4692            * - **number**: A fixed number of pixels to be used as offset.<br /><br />
4693            * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
4694            *   a number representing the offset (in pixels).<br /><br />
4695            * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
4696            *   the top of the page to the element's bottom will be used as offset.<br />
4697            *   **Note**: The element will be taken into account only as long as its `position` is set to
4698            *   `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
4699            *   their height and/or positioning according to the viewport's size.
4700            *
4701            * <br />
4702            * <div class="alert alert-warning">
4703            * In order for `yOffset` to work properly, scrolling should take place on the document's root and
4704            * not some child element.
4705            * </div>
4706            *
4707            * @example
4708              <example module="anchorScrollExample">
4709                <file name="index.html">
4710                  <div id="scrollArea" ng-controller="ScrollController">
4711                    <a ng-click="gotoBottom()">Go to bottom</a>
4712                    <a id="bottom"></a> You're at the bottom!
4713                  </div>
4714                </file>
4715                <file name="script.js">
4716                  angular.module('anchorScrollExample', [])
4717                    .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
4718                      function ($scope, $location, $anchorScroll) {
4719                        $scope.gotoBottom = function() {
4720                          // set the location.hash to the id of
4721                          // the element you wish to scroll to.
4722                          $location.hash('bottom');
4723
4724                          // call $anchorScroll()
4725                          $anchorScroll();
4726                        };
4727                      }]);
4728                </file>
4729                <file name="style.css">
4730                  #scrollArea {
4731                    height: 280px;
4732                    overflow: auto;
4733                  }
4734
4735                  #bottom {
4736                    display: block;
4737                    margin-top: 2000px;
4738                  }
4739                </file>
4740              </example>
4741            *
4742            * <hr />
4743            * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
4744            * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
4745            *
4746            * @example
4747              <example module="anchorScrollOffsetExample">
4748                <file name="index.html">
4749                  <div class="fixed-header" ng-controller="headerCtrl">
4750                    <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
4751                      Go to anchor {{x}}
4752                    </a>
4753                  </div>
4754                  <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
4755                    Anchor {{x}} of 5
4756                  </div>
4757                </file>
4758                <file name="script.js">
4759                  angular.module('anchorScrollOffsetExample', [])
4760                    .run(['$anchorScroll', function($anchorScroll) {
4761                      $anchorScroll.yOffset = 50;   // always scroll by 50 extra pixels
4762                    }])
4763                    .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
4764                      function ($anchorScroll, $location, $scope) {
4765                        $scope.gotoAnchor = function(x) {
4766                          var newHash = 'anchor' + x;
4767                          if ($location.hash() !== newHash) {
4768                            // set the $location.hash to `newHash` and
4769                            // $anchorScroll will automatically scroll to it
4770                            $location.hash('anchor' + x);
4771                          } else {
4772                            // call $anchorScroll() explicitly,
4773                            // since $location.hash hasn't changed
4774                            $anchorScroll();
4775                          }
4776                        };
4777                      }
4778                    ]);
4779                </file>
4780                <file name="style.css">
4781                  body {
4782                    padding-top: 50px;
4783                  }
4784
4785                  .anchor {
4786                    border: 2px dashed DarkOrchid;
4787                    padding: 10px 10px 200px 10px;
4788                  }
4789
4790                  .fixed-header {
4791                    background-color: rgba(0, 0, 0, 0.2);
4792                    height: 50px;
4793                    position: fixed;
4794                    top: 0; left: 0; right: 0;
4795                  }
4796
4797                  .fixed-header > a {
4798                    display: inline-block;
4799                    margin: 5px 15px;
4800                  }
4801                </file>
4802              </example>
4803            */
4804           this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
4805             var document = $window.document;
4806
4807             // Helper function to get first anchor from a NodeList
4808             // (using `Array#some()` instead of `angular#forEach()` since it's more performant
4809             //  and working in all supported browsers.)
4810             function getFirstAnchor(list) {
4811               var result = null;
4812               Array.prototype.some.call(list, function(element) {
4813                 if (nodeName_(element) === 'a') {
4814                   result = element;
4815                   return true;
4816                 }
4817               });
4818               return result;
4819             }
4820
4821             function getYOffset() {
4822
4823               var offset = scroll.yOffset;
4824
4825               if (isFunction(offset)) {
4826                 offset = offset();
4827               } else if (isElement(offset)) {
4828                 var elem = offset[0];
4829                 var style = $window.getComputedStyle(elem);
4830                 if (style.position !== 'fixed') {
4831                   offset = 0;
4832                 } else {
4833                   offset = elem.getBoundingClientRect().bottom;
4834                 }
4835               } else if (!isNumber(offset)) {
4836                 offset = 0;
4837               }
4838
4839               return offset;
4840             }
4841
4842             function scrollTo(elem) {
4843               if (elem) {
4844                 elem.scrollIntoView();
4845
4846                 var offset = getYOffset();
4847
4848                 if (offset) {
4849                   // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
4850                   // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
4851                   // top of the viewport.
4852                   //
4853                   // IF the number of pixels from the top of `elem` to the end of the page's content is less
4854                   // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
4855                   // way down the page.
4856                   //
4857                   // This is often the case for elements near the bottom of the page.
4858                   //
4859                   // In such cases we do not need to scroll the whole `offset` up, just the difference between
4860                   // the top of the element and the offset, which is enough to align the top of `elem` at the
4861                   // desired position.
4862                   var elemTop = elem.getBoundingClientRect().top;
4863                   $window.scrollBy(0, elemTop - offset);
4864                 }
4865               } else {
4866                 $window.scrollTo(0, 0);
4867               }
4868             }
4869
4870             function scroll(hash) {
4871               hash = isString(hash) ? hash : $location.hash();
4872               var elm;
4873
4874               // empty hash, scroll to the top of the page
4875               if (!hash) scrollTo(null);
4876
4877               // element with given id
4878               else if ((elm = document.getElementById(hash))) scrollTo(elm);
4879
4880               // first anchor with given name :-D
4881               else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
4882
4883               // no element and hash == 'top', scroll to the top of the page
4884               else if (hash === 'top') scrollTo(null);
4885             }
4886
4887             // does not scroll when user clicks on anchor link that is currently on
4888             // (no url change, no $location.hash() change), browser native does scroll
4889             if (autoScrollingEnabled) {
4890               $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
4891                 function autoScrollWatchAction(newVal, oldVal) {
4892                   // skip the initial scroll if $location.hash is empty
4893                   if (newVal === oldVal && newVal === '') return;
4894
4895                   jqLiteDocumentLoaded(function() {
4896                     $rootScope.$evalAsync(scroll);
4897                   });
4898                 });
4899             }
4900
4901             return scroll;
4902           }];
4903         }
4904
4905         var $animateMinErr = minErr('$animate');
4906         var ELEMENT_NODE = 1;
4907         var NG_ANIMATE_CLASSNAME = 'ng-animate';
4908
4909         function mergeClasses(a,b) {
4910           if (!a && !b) return '';
4911           if (!a) return b;
4912           if (!b) return a;
4913           if (isArray(a)) a = a.join(' ');
4914           if (isArray(b)) b = b.join(' ');
4915           return a + ' ' + b;
4916         }
4917
4918         function extractElementNode(element) {
4919           for (var i = 0; i < element.length; i++) {
4920             var elm = element[i];
4921             if (elm.nodeType === ELEMENT_NODE) {
4922               return elm;
4923             }
4924           }
4925         }
4926
4927         function splitClasses(classes) {
4928           if (isString(classes)) {
4929             classes = classes.split(' ');
4930           }
4931
4932           // Use createMap() to prevent class assumptions involving property names in
4933           // Object.prototype
4934           var obj = createMap();
4935           forEach(classes, function(klass) {
4936             // sometimes the split leaves empty string values
4937             // incase extra spaces were applied to the options
4938             if (klass.length) {
4939               obj[klass] = true;
4940             }
4941           });
4942           return obj;
4943         }
4944
4945         // if any other type of options value besides an Object value is
4946         // passed into the $animate.method() animation then this helper code
4947         // will be run which will ignore it. While this patch is not the
4948         // greatest solution to this, a lot of existing plugins depend on
4949         // $animate to either call the callback (< 1.2) or return a promise
4950         // that can be changed. This helper function ensures that the options
4951         // are wiped clean incase a callback function is provided.
4952         function prepareAnimateOptions(options) {
4953           return isObject(options)
4954               ? options
4955               : {};
4956         }
4957
4958         var $$CoreAnimateRunnerProvider = function() {
4959           this.$get = ['$q', '$$rAF', function($q, $$rAF) {
4960             function AnimateRunner() {}
4961             AnimateRunner.all = noop;
4962             AnimateRunner.chain = noop;
4963             AnimateRunner.prototype = {
4964               end: noop,
4965               cancel: noop,
4966               resume: noop,
4967               pause: noop,
4968               complete: noop,
4969               then: function(pass, fail) {
4970                 return $q(function(resolve) {
4971                   $$rAF(function() {
4972                     resolve();
4973                   });
4974                 }).then(pass, fail);
4975               }
4976             };
4977             return AnimateRunner;
4978           }];
4979         };
4980
4981         // this is prefixed with Core since it conflicts with
4982         // the animateQueueProvider defined in ngAnimate/animateQueue.js
4983         var $$CoreAnimateQueueProvider = function() {
4984           var postDigestQueue = new HashMap();
4985           var postDigestElements = [];
4986
4987           this.$get = ['$$AnimateRunner', '$rootScope',
4988                function($$AnimateRunner,   $rootScope) {
4989             return {
4990               enabled: noop,
4991               on: noop,
4992               off: noop,
4993               pin: noop,
4994
4995               push: function(element, event, options, domOperation) {
4996                 domOperation        && domOperation();
4997
4998                 options = options || {};
4999                 options.from        && element.css(options.from);
5000                 options.to          && element.css(options.to);
5001
5002                 if (options.addClass || options.removeClass) {
5003                   addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
5004                 }
5005
5006                 return new $$AnimateRunner(); // jshint ignore:line
5007               }
5008             };
5009
5010
5011             function updateData(data, classes, value) {
5012               var changed = false;
5013               if (classes) {
5014                 classes = isString(classes) ? classes.split(' ') :
5015                           isArray(classes) ? classes : [];
5016                 forEach(classes, function(className) {
5017                   if (className) {
5018                     changed = true;
5019                     data[className] = value;
5020                   }
5021                 });
5022               }
5023               return changed;
5024             }
5025
5026             function handleCSSClassChanges() {
5027               forEach(postDigestElements, function(element) {
5028                 var data = postDigestQueue.get(element);
5029                 if (data) {
5030                   var existing = splitClasses(element.attr('class'));
5031                   var toAdd = '';
5032                   var toRemove = '';
5033                   forEach(data, function(status, className) {
5034                     var hasClass = !!existing[className];
5035                     if (status !== hasClass) {
5036                       if (status) {
5037                         toAdd += (toAdd.length ? ' ' : '') + className;
5038                       } else {
5039                         toRemove += (toRemove.length ? ' ' : '') + className;
5040                       }
5041                     }
5042                   });
5043
5044                   forEach(element, function(elm) {
5045                     toAdd    && jqLiteAddClass(elm, toAdd);
5046                     toRemove && jqLiteRemoveClass(elm, toRemove);
5047                   });
5048                   postDigestQueue.remove(element);
5049                 }
5050               });
5051               postDigestElements.length = 0;
5052             }
5053
5054
5055             function addRemoveClassesPostDigest(element, add, remove) {
5056               var data = postDigestQueue.get(element) || {};
5057
5058               var classesAdded = updateData(data, add, true);
5059               var classesRemoved = updateData(data, remove, false);
5060
5061               if (classesAdded || classesRemoved) {
5062
5063                 postDigestQueue.put(element, data);
5064                 postDigestElements.push(element);
5065
5066                 if (postDigestElements.length === 1) {
5067                   $rootScope.$$postDigest(handleCSSClassChanges);
5068                 }
5069               }
5070             }
5071           }];
5072         };
5073
5074         /**
5075          * @ngdoc provider
5076          * @name $animateProvider
5077          *
5078          * @description
5079          * Default implementation of $animate that doesn't perform any animations, instead just
5080          * synchronously performs DOM updates and resolves the returned runner promise.
5081          *
5082          * In order to enable animations the `ngAnimate` module has to be loaded.
5083          *
5084          * To see the functional implementation check out `src/ngAnimate/animate.js`.
5085          */
5086         var $AnimateProvider = ['$provide', function($provide) {
5087           var provider = this;
5088
5089           this.$$registeredAnimations = Object.create(null);
5090
5091            /**
5092            * @ngdoc method
5093            * @name $animateProvider#register
5094            *
5095            * @description
5096            * Registers a new injectable animation factory function. The factory function produces the
5097            * animation object which contains callback functions for each event that is expected to be
5098            * animated.
5099            *
5100            *   * `eventFn`: `function(element, ... , doneFunction, options)`
5101            *   The element to animate, the `doneFunction` and the options fed into the animation. Depending
5102            *   on the type of animation additional arguments will be injected into the animation function. The
5103            *   list below explains the function signatures for the different animation methods:
5104            *
5105            *   - setClass: function(element, addedClasses, removedClasses, doneFunction, options)
5106            *   - addClass: function(element, addedClasses, doneFunction, options)
5107            *   - removeClass: function(element, removedClasses, doneFunction, options)
5108            *   - enter, leave, move: function(element, doneFunction, options)
5109            *   - animate: function(element, fromStyles, toStyles, doneFunction, options)
5110            *
5111            *   Make sure to trigger the `doneFunction` once the animation is fully complete.
5112            *
5113            * ```js
5114            *   return {
5115            *     //enter, leave, move signature
5116            *     eventFn : function(element, done, options) {
5117            *       //code to run the animation
5118            *       //once complete, then run done()
5119            *       return function endFunction(wasCancelled) {
5120            *         //code to cancel the animation
5121            *       }
5122            *     }
5123            *   }
5124            * ```
5125            *
5126            * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to).
5127            * @param {Function} factory The factory function that will be executed to return the animation
5128            *                           object.
5129            */
5130           this.register = function(name, factory) {
5131             if (name && name.charAt(0) !== '.') {
5132               throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name);
5133             }
5134
5135             var key = name + '-animation';
5136             provider.$$registeredAnimations[name.substr(1)] = key;
5137             $provide.factory(key, factory);
5138           };
5139
5140           /**
5141            * @ngdoc method
5142            * @name $animateProvider#classNameFilter
5143            *
5144            * @description
5145            * Sets and/or returns the CSS class regular expression that is checked when performing
5146            * an animation. Upon bootstrap the classNameFilter value is not set at all and will
5147            * therefore enable $animate to attempt to perform an animation on any element that is triggered.
5148            * When setting the `classNameFilter` value, animations will only be performed on elements
5149            * that successfully match the filter expression. This in turn can boost performance
5150            * for low-powered devices as well as applications containing a lot of structural operations.
5151            * @param {RegExp=} expression The className expression which will be checked against all animations
5152            * @return {RegExp} The current CSS className expression value. If null then there is no expression value
5153            */
5154           this.classNameFilter = function(expression) {
5155             if (arguments.length === 1) {
5156               this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
5157               if (this.$$classNameFilter) {
5158                 var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)");
5159                 if (reservedRegex.test(this.$$classNameFilter.toString())) {
5160                   throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME);
5161
5162                 }
5163               }
5164             }
5165             return this.$$classNameFilter;
5166           };
5167
5168           this.$get = ['$$animateQueue', function($$animateQueue) {
5169             function domInsert(element, parentElement, afterElement) {
5170               // if for some reason the previous element was removed
5171               // from the dom sometime before this code runs then let's
5172               // just stick to using the parent element as the anchor
5173               if (afterElement) {
5174                 var afterNode = extractElementNode(afterElement);
5175                 if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) {
5176                   afterElement = null;
5177                 }
5178               }
5179               afterElement ? afterElement.after(element) : parentElement.prepend(element);
5180             }
5181
5182             /**
5183              * @ngdoc service
5184              * @name $animate
5185              * @description The $animate service exposes a series of DOM utility methods that provide support
5186              * for animation hooks. The default behavior is the application of DOM operations, however,
5187              * when an animation is detected (and animations are enabled), $animate will do the heavy lifting
5188              * to ensure that animation runs with the triggered DOM operation.
5189              *
5190              * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't
5191              * included and only when it is active then the animation hooks that `$animate` triggers will be
5192              * functional. Once active then all structural `ng-` directives will trigger animations as they perform
5193              * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
5194              * `ngShow`, `ngHide` and `ngMessages` also provide support for animations.
5195              *
5196              * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives.
5197              *
5198              * To learn more about enabling animation support, click here to visit the
5199              * {@link ngAnimate ngAnimate module page}.
5200              */
5201             return {
5202               // we don't call it directly since non-existant arguments may
5203               // be interpreted as null within the sub enabled function
5204
5205               /**
5206                *
5207                * @ngdoc method
5208                * @name $animate#on
5209                * @kind function
5210                * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...)
5211                *    has fired on the given element or among any of its children. Once the listener is fired, the provided callback
5212                *    is fired with the following params:
5213                *
5214                * ```js
5215                * $animate.on('enter', container,
5216                *    function callback(element, phase) {
5217                *      // cool we detected an enter animation within the container
5218                *    }
5219                * );
5220                * ```
5221                *
5222                * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...)
5223                * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself
5224                *     as well as among its children
5225                * @param {Function} callback the callback function that will be fired when the listener is triggered
5226                *
5227                * The arguments present in the callback function are:
5228                * * `element` - The captured DOM element that the animation was fired on.
5229                * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends).
5230                */
5231               on: $$animateQueue.on,
5232
5233               /**
5234                *
5235                * @ngdoc method
5236                * @name $animate#off
5237                * @kind function
5238                * @description Deregisters an event listener based on the event which has been associated with the provided element. This method
5239                * can be used in three different ways depending on the arguments:
5240                *
5241                * ```js
5242                * // remove all the animation event listeners listening for `enter`
5243                * $animate.off('enter');
5244                *
5245                * // remove all the animation event listeners listening for `enter` on the given element and its children
5246                * $animate.off('enter', container);
5247                *
5248                * // remove the event listener function provided by `listenerFn` that is set
5249                * // to listen for `enter` on the given `element` as well as its children
5250                * $animate.off('enter', container, callback);
5251                * ```
5252                *
5253                * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
5254                * @param {DOMElement=} container the container element the event listener was placed on
5255                * @param {Function=} callback the callback function that was registered as the listener
5256                */
5257               off: $$animateQueue.off,
5258
5259               /**
5260                * @ngdoc method
5261                * @name $animate#pin
5262                * @kind function
5263                * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists
5264                *    outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the
5265                *    element despite being outside the realm of the application or within another application. Say for example if the application
5266                *    was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated
5267                *    as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind
5268                *    that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association.
5269                *
5270                *    Note that this feature is only active when the `ngAnimate` module is used.
5271                *
5272                * @param {DOMElement} element the external element that will be pinned
5273                * @param {DOMElement} parentElement the host parent element that will be associated with the external element
5274                */
5275               pin: $$animateQueue.pin,
5276
5277               /**
5278                *
5279                * @ngdoc method
5280                * @name $animate#enabled
5281                * @kind function
5282                * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This
5283                * function can be called in four ways:
5284                *
5285                * ```js
5286                * // returns true or false
5287                * $animate.enabled();
5288                *
5289                * // changes the enabled state for all animations
5290                * $animate.enabled(false);
5291                * $animate.enabled(true);
5292                *
5293                * // returns true or false if animations are enabled for an element
5294                * $animate.enabled(element);
5295                *
5296                * // changes the enabled state for an element and its children
5297                * $animate.enabled(element, true);
5298                * $animate.enabled(element, false);
5299                * ```
5300                *
5301                * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state
5302                * @param {boolean=} enabled whether or not the animations will be enabled for the element
5303                *
5304                * @return {boolean} whether or not animations are enabled
5305                */
5306               enabled: $$animateQueue.enabled,
5307
5308               /**
5309                * @ngdoc method
5310                * @name $animate#cancel
5311                * @kind function
5312                * @description Cancels the provided animation.
5313                *
5314                * @param {Promise} animationPromise The animation promise that is returned when an animation is started.
5315                */
5316               cancel: function(runner) {
5317                 runner.end && runner.end();
5318               },
5319
5320               /**
5321                *
5322                * @ngdoc method
5323                * @name $animate#enter
5324                * @kind function
5325                * @description Inserts the element into the DOM either after the `after` element (if provided) or
5326                *   as the first child within the `parent` element and then triggers an animation.
5327                *   A promise is returned that will be resolved during the next digest once the animation
5328                *   has completed.
5329                *
5330                * @param {DOMElement} element the element which will be inserted into the DOM
5331                * @param {DOMElement} parent the parent element which will append the element as
5332                *   a child (so long as the after element is not present)
5333                * @param {DOMElement=} after the sibling element after which the element will be appended
5334                * @param {object=} options an optional collection of options/styles that will be applied to the element
5335                *
5336                * @return {Promise} the animation callback promise
5337                */
5338               enter: function(element, parent, after, options) {
5339                 parent = parent && jqLite(parent);
5340                 after = after && jqLite(after);
5341                 parent = parent || after.parent();
5342                 domInsert(element, parent, after);
5343                 return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options));
5344               },
5345
5346               /**
5347                *
5348                * @ngdoc method
5349                * @name $animate#move
5350                * @kind function
5351                * @description Inserts (moves) the element into its new position in the DOM either after
5352                *   the `after` element (if provided) or as the first child within the `parent` element
5353                *   and then triggers an animation. A promise is returned that will be resolved
5354                *   during the next digest once the animation has completed.
5355                *
5356                * @param {DOMElement} element the element which will be moved into the new DOM position
5357                * @param {DOMElement} parent the parent element which will append the element as
5358                *   a child (so long as the after element is not present)
5359                * @param {DOMElement=} after the sibling element after which the element will be appended
5360                * @param {object=} options an optional collection of options/styles that will be applied to the element
5361                *
5362                * @return {Promise} the animation callback promise
5363                */
5364               move: function(element, parent, after, options) {
5365                 parent = parent && jqLite(parent);
5366                 after = after && jqLite(after);
5367                 parent = parent || after.parent();
5368                 domInsert(element, parent, after);
5369                 return $$animateQueue.push(element, 'move', prepareAnimateOptions(options));
5370               },
5371
5372               /**
5373                * @ngdoc method
5374                * @name $animate#leave
5375                * @kind function
5376                * @description Triggers an animation and then removes the element from the DOM.
5377                * When the function is called a promise is returned that will be resolved during the next
5378                * digest once the animation has completed.
5379                *
5380                * @param {DOMElement} element the element which will be removed from the DOM
5381                * @param {object=} options an optional collection of options/styles that will be applied to the element
5382                *
5383                * @return {Promise} the animation callback promise
5384                */
5385               leave: function(element, options) {
5386                 return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {
5387                   element.remove();
5388                 });
5389               },
5390
5391               /**
5392                * @ngdoc method
5393                * @name $animate#addClass
5394                * @kind function
5395                *
5396                * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon
5397                *   execution, the addClass operation will only be handled after the next digest and it will not trigger an
5398                *   animation if element already contains the CSS class or if the class is removed at a later step.
5399                *   Note that class-based animations are treated differently compared to structural animations
5400                *   (like enter, move and leave) since the CSS classes may be added/removed at different points
5401                *   depending if CSS or JavaScript animations are used.
5402                *
5403                * @param {DOMElement} element the element which the CSS classes will be applied to
5404                * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
5405                * @param {object=} options an optional collection of options/styles that will be applied to the element
5406                *
5407                * @return {Promise} the animation callback promise
5408                */
5409               addClass: function(element, className, options) {
5410                 options = prepareAnimateOptions(options);
5411                 options.addClass = mergeClasses(options.addclass, className);
5412                 return $$animateQueue.push(element, 'addClass', options);
5413               },
5414
5415               /**
5416                * @ngdoc method
5417                * @name $animate#removeClass
5418                * @kind function
5419                *
5420                * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon
5421                *   execution, the removeClass operation will only be handled after the next digest and it will not trigger an
5422                *   animation if element does not contain the CSS class or if the class is added at a later step.
5423                *   Note that class-based animations are treated differently compared to structural animations
5424                *   (like enter, move and leave) since the CSS classes may be added/removed at different points
5425                *   depending if CSS or JavaScript animations are used.
5426                *
5427                * @param {DOMElement} element the element which the CSS classes will be applied to
5428                * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
5429                * @param {object=} options an optional collection of options/styles that will be applied to the element
5430                *
5431                * @return {Promise} the animation callback promise
5432                */
5433               removeClass: function(element, className, options) {
5434                 options = prepareAnimateOptions(options);
5435                 options.removeClass = mergeClasses(options.removeClass, className);
5436                 return $$animateQueue.push(element, 'removeClass', options);
5437               },
5438
5439               /**
5440                * @ngdoc method
5441                * @name $animate#setClass
5442                * @kind function
5443                *
5444                * @description Performs both the addition and removal of a CSS classes on an element and (during the process)
5445                *    triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and
5446                *    `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has
5447                *    passed. Note that class-based animations are treated differently compared to structural animations
5448                *    (like enter, move and leave) since the CSS classes may be added/removed at different points
5449                *    depending if CSS or JavaScript animations are used.
5450                *
5451                * @param {DOMElement} element the element which the CSS classes will be applied to
5452                * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces)
5453                * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)
5454                * @param {object=} options an optional collection of options/styles that will be applied to the element
5455                *
5456                * @return {Promise} the animation callback promise
5457                */
5458               setClass: function(element, add, remove, options) {
5459                 options = prepareAnimateOptions(options);
5460                 options.addClass = mergeClasses(options.addClass, add);
5461                 options.removeClass = mergeClasses(options.removeClass, remove);
5462                 return $$animateQueue.push(element, 'setClass', options);
5463               },
5464
5465               /**
5466                * @ngdoc method
5467                * @name $animate#animate
5468                * @kind function
5469                *
5470                * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
5471                * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take
5472                * on the provided styles. For example, if a transition animation is set for the given className then the provided from and
5473                * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles
5474                * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter).
5475                *
5476                * @param {DOMElement} element the element which the CSS styles will be applied to
5477                * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
5478                * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
5479                * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
5480                *    this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
5481                *    (Note that if no animation is detected then this value will not be appplied to the element.)
5482                * @param {object=} options an optional collection of options/styles that will be applied to the element
5483                *
5484                * @return {Promise} the animation callback promise
5485                */
5486               animate: function(element, from, to, className, options) {
5487                 options = prepareAnimateOptions(options);
5488                 options.from = options.from ? extend(options.from, from) : from;
5489                 options.to   = options.to   ? extend(options.to, to)     : to;
5490
5491                 className = className || 'ng-inline-animate';
5492                 options.tempClasses = mergeClasses(options.tempClasses, className);
5493                 return $$animateQueue.push(element, 'animate', options);
5494               }
5495             };
5496           }];
5497         }];
5498
5499         /**
5500          * @ngdoc service
5501          * @name $animateCss
5502          * @kind object
5503          *
5504          * @description
5505          * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
5506          * then the `$animateCss` service will actually perform animations.
5507          *
5508          * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
5509          */
5510         var $CoreAnimateCssProvider = function() {
5511           this.$get = ['$$rAF', '$q', function($$rAF, $q) {
5512
5513             var RAFPromise = function() {};
5514             RAFPromise.prototype = {
5515               done: function(cancel) {
5516                 this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
5517               },
5518               end: function() {
5519                 this.done();
5520               },
5521               cancel: function() {
5522                 this.done(true);
5523               },
5524               getPromise: function() {
5525                 if (!this.defer) {
5526                   this.defer = $q.defer();
5527                 }
5528                 return this.defer.promise;
5529               },
5530               then: function(f1,f2) {
5531                 return this.getPromise().then(f1,f2);
5532               },
5533               'catch': function(f1) {
5534                 return this.getPromise()['catch'](f1);
5535               },
5536               'finally': function(f1) {
5537                 return this.getPromise()['finally'](f1);
5538               }
5539             };
5540
5541             return function(element, options) {
5542               // there is no point in applying the styles since
5543               // there is no animation that goes on at all in
5544               // this version of $animateCss.
5545               if (options.cleanupStyles) {
5546                 options.from = options.to = null;
5547               }
5548
5549               if (options.from) {
5550                 element.css(options.from);
5551                 options.from = null;
5552               }
5553
5554               var closed, runner = new RAFPromise();
5555               return {
5556                 start: run,
5557                 end: run
5558               };
5559
5560               function run() {
5561                 $$rAF(function() {
5562                   close();
5563                   if (!closed) {
5564                     runner.done();
5565                   }
5566                   closed = true;
5567                 });
5568                 return runner;
5569               }
5570
5571               function close() {
5572                 if (options.addClass) {
5573                   element.addClass(options.addClass);
5574                   options.addClass = null;
5575                 }
5576                 if (options.removeClass) {
5577                   element.removeClass(options.removeClass);
5578                   options.removeClass = null;
5579                 }
5580                 if (options.to) {
5581                   element.css(options.to);
5582                   options.to = null;
5583                 }
5584               }
5585             };
5586           }];
5587         };
5588
5589         /* global stripHash: true */
5590
5591         /**
5592          * ! This is a private undocumented service !
5593          *
5594          * @name $browser
5595          * @requires $log
5596          * @description
5597          * This object has two goals:
5598          *
5599          * - hide all the global state in the browser caused by the window object
5600          * - abstract away all the browser specific features and inconsistencies
5601          *
5602          * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
5603          * service, which can be used for convenient testing of the application without the interaction with
5604          * the real browser apis.
5605          */
5606         /**
5607          * @param {object} window The global window object.
5608          * @param {object} document jQuery wrapped document.
5609          * @param {object} $log window.console or an object with the same interface.
5610          * @param {object} $sniffer $sniffer service
5611          */
5612         function Browser(window, document, $log, $sniffer) {
5613           var self = this,
5614               rawDocument = document[0],
5615               location = window.location,
5616               history = window.history,
5617               setTimeout = window.setTimeout,
5618               clearTimeout = window.clearTimeout,
5619               pendingDeferIds = {};
5620
5621           self.isMock = false;
5622
5623           var outstandingRequestCount = 0;
5624           var outstandingRequestCallbacks = [];
5625
5626           // TODO(vojta): remove this temporary api
5627           self.$$completeOutstandingRequest = completeOutstandingRequest;
5628           self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
5629
5630           /**
5631            * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
5632            * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
5633            */
5634           function completeOutstandingRequest(fn) {
5635             try {
5636               fn.apply(null, sliceArgs(arguments, 1));
5637             } finally {
5638               outstandingRequestCount--;
5639               if (outstandingRequestCount === 0) {
5640                 while (outstandingRequestCallbacks.length) {
5641                   try {
5642                     outstandingRequestCallbacks.pop()();
5643                   } catch (e) {
5644                     $log.error(e);
5645                   }
5646                 }
5647               }
5648             }
5649           }
5650
5651           function getHash(url) {
5652             var index = url.indexOf('#');
5653             return index === -1 ? '' : url.substr(index);
5654           }
5655
5656           /**
5657            * @private
5658            * Note: this method is used only by scenario runner
5659            * TODO(vojta): prefix this method with $$ ?
5660            * @param {function()} callback Function that will be called when no outstanding request
5661            */
5662           self.notifyWhenNoOutstandingRequests = function(callback) {
5663             if (outstandingRequestCount === 0) {
5664               callback();
5665             } else {
5666               outstandingRequestCallbacks.push(callback);
5667             }
5668           };
5669
5670           //////////////////////////////////////////////////////////////
5671           // URL API
5672           //////////////////////////////////////////////////////////////
5673
5674           var cachedState, lastHistoryState,
5675               lastBrowserUrl = location.href,
5676               baseElement = document.find('base'),
5677               pendingLocation = null;
5678
5679           cacheState();
5680           lastHistoryState = cachedState;
5681
5682           /**
5683            * @name $browser#url
5684            *
5685            * @description
5686            * GETTER:
5687            * Without any argument, this method just returns current value of location.href.
5688            *
5689            * SETTER:
5690            * With at least one argument, this method sets url to new value.
5691            * If html5 history api supported, pushState/replaceState is used, otherwise
5692            * location.href/location.replace is used.
5693            * Returns its own instance to allow chaining
5694            *
5695            * NOTE: this api is intended for use only by the $location service. Please use the
5696            * {@link ng.$location $location service} to change url.
5697            *
5698            * @param {string} url New url (when used as setter)
5699            * @param {boolean=} replace Should new url replace current history record?
5700            * @param {object=} state object to use with pushState/replaceState
5701            */
5702           self.url = function(url, replace, state) {
5703             // In modern browsers `history.state` is `null` by default; treating it separately
5704             // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
5705             // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
5706             if (isUndefined(state)) {
5707               state = null;
5708             }
5709
5710             // Android Browser BFCache causes location, history reference to become stale.
5711             if (location !== window.location) location = window.location;
5712             if (history !== window.history) history = window.history;
5713
5714             // setter
5715             if (url) {
5716               var sameState = lastHistoryState === state;
5717
5718               // Don't change anything if previous and current URLs and states match. This also prevents
5719               // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
5720               // See https://github.com/angular/angular.js/commit/ffb2701
5721               if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
5722                 return self;
5723               }
5724               var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
5725               lastBrowserUrl = url;
5726               lastHistoryState = state;
5727               // Don't use history API if only the hash changed
5728               // due to a bug in IE10/IE11 which leads
5729               // to not firing a `hashchange` nor `popstate` event
5730               // in some cases (see #9143).
5731               if ($sniffer.history && (!sameBase || !sameState)) {
5732                 history[replace ? 'replaceState' : 'pushState'](state, '', url);
5733                 cacheState();
5734                 // Do the assignment again so that those two variables are referentially identical.
5735                 lastHistoryState = cachedState;
5736               } else {
5737                 if (!sameBase || pendingLocation) {
5738                   pendingLocation = url;
5739                 }
5740                 if (replace) {
5741                   location.replace(url);
5742                 } else if (!sameBase) {
5743                   location.href = url;
5744                 } else {
5745                   location.hash = getHash(url);
5746                 }
5747                 if (location.href !== url) {
5748                   pendingLocation = url;
5749                 }
5750               }
5751               return self;
5752             // getter
5753             } else {
5754               // - pendingLocation is needed as browsers don't allow to read out
5755               //   the new location.href if a reload happened or if there is a bug like in iOS 9 (see
5756               //   https://openradar.appspot.com/22186109).
5757               // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
5758               return pendingLocation || location.href.replace(/%27/g,"'");
5759             }
5760           };
5761
5762           /**
5763            * @name $browser#state
5764            *
5765            * @description
5766            * This method is a getter.
5767            *
5768            * Return history.state or null if history.state is undefined.
5769            *
5770            * @returns {object} state
5771            */
5772           self.state = function() {
5773             return cachedState;
5774           };
5775
5776           var urlChangeListeners = [],
5777               urlChangeInit = false;
5778
5779           function cacheStateAndFireUrlChange() {
5780             pendingLocation = null;
5781             cacheState();
5782             fireUrlChange();
5783           }
5784
5785           function getCurrentState() {
5786             try {
5787               return history.state;
5788             } catch (e) {
5789               // MSIE can reportedly throw when there is no state (UNCONFIRMED).
5790             }
5791           }
5792
5793           // This variable should be used *only* inside the cacheState function.
5794           var lastCachedState = null;
5795           function cacheState() {
5796             // This should be the only place in $browser where `history.state` is read.
5797             cachedState = getCurrentState();
5798             cachedState = isUndefined(cachedState) ? null : cachedState;
5799
5800             // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
5801             if (equals(cachedState, lastCachedState)) {
5802               cachedState = lastCachedState;
5803             }
5804             lastCachedState = cachedState;
5805           }
5806
5807           function fireUrlChange() {
5808             if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
5809               return;
5810             }
5811
5812             lastBrowserUrl = self.url();
5813             lastHistoryState = cachedState;
5814             forEach(urlChangeListeners, function(listener) {
5815               listener(self.url(), cachedState);
5816             });
5817           }
5818
5819           /**
5820            * @name $browser#onUrlChange
5821            *
5822            * @description
5823            * Register callback function that will be called, when url changes.
5824            *
5825            * It's only called when the url is changed from outside of angular:
5826            * - user types different url into address bar
5827            * - user clicks on history (forward/back) button
5828            * - user clicks on a link
5829            *
5830            * It's not called when url is changed by $browser.url() method
5831            *
5832            * The listener gets called with new url as parameter.
5833            *
5834            * NOTE: this api is intended for use only by the $location service. Please use the
5835            * {@link ng.$location $location service} to monitor url changes in angular apps.
5836            *
5837            * @param {function(string)} listener Listener function to be called when url changes.
5838            * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
5839            */
5840           self.onUrlChange = function(callback) {
5841             // TODO(vojta): refactor to use node's syntax for events
5842             if (!urlChangeInit) {
5843               // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
5844               // don't fire popstate when user change the address bar and don't fire hashchange when url
5845               // changed by push/replaceState
5846
5847               // html5 history api - popstate event
5848               if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
5849               // hashchange event
5850               jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
5851
5852               urlChangeInit = true;
5853             }
5854
5855             urlChangeListeners.push(callback);
5856             return callback;
5857           };
5858
5859           /**
5860            * @private
5861            * Remove popstate and hashchange handler from window.
5862            *
5863            * NOTE: this api is intended for use only by $rootScope.
5864            */
5865           self.$$applicationDestroyed = function() {
5866             jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);
5867           };
5868
5869           /**
5870            * Checks whether the url has changed outside of Angular.
5871            * Needs to be exported to be able to check for changes that have been done in sync,
5872            * as hashchange/popstate events fire in async.
5873            */
5874           self.$$checkUrlChange = fireUrlChange;
5875
5876           //////////////////////////////////////////////////////////////
5877           // Misc API
5878           //////////////////////////////////////////////////////////////
5879
5880           /**
5881            * @name $browser#baseHref
5882            *
5883            * @description
5884            * Returns current <base href>
5885            * (always relative - without domain)
5886            *
5887            * @returns {string} The current base href
5888            */
5889           self.baseHref = function() {
5890             var href = baseElement.attr('href');
5891             return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
5892           };
5893
5894           /**
5895            * @name $browser#defer
5896            * @param {function()} fn A function, who's execution should be deferred.
5897            * @param {number=} [delay=0] of milliseconds to defer the function execution.
5898            * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
5899            *
5900            * @description
5901            * Executes a fn asynchronously via `setTimeout(fn, delay)`.
5902            *
5903            * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
5904            * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
5905            * via `$browser.defer.flush()`.
5906            *
5907            */
5908           self.defer = function(fn, delay) {
5909             var timeoutId;
5910             outstandingRequestCount++;
5911             timeoutId = setTimeout(function() {
5912               delete pendingDeferIds[timeoutId];
5913               completeOutstandingRequest(fn);
5914             }, delay || 0);
5915             pendingDeferIds[timeoutId] = true;
5916             return timeoutId;
5917           };
5918
5919
5920           /**
5921            * @name $browser#defer.cancel
5922            *
5923            * @description
5924            * Cancels a deferred task identified with `deferId`.
5925            *
5926            * @param {*} deferId Token returned by the `$browser.defer` function.
5927            * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
5928            *                    canceled.
5929            */
5930           self.defer.cancel = function(deferId) {
5931             if (pendingDeferIds[deferId]) {
5932               delete pendingDeferIds[deferId];
5933               clearTimeout(deferId);
5934               completeOutstandingRequest(noop);
5935               return true;
5936             }
5937             return false;
5938           };
5939
5940         }
5941
5942         function $BrowserProvider() {
5943           this.$get = ['$window', '$log', '$sniffer', '$document',
5944               function($window, $log, $sniffer, $document) {
5945                 return new Browser($window, $document, $log, $sniffer);
5946               }];
5947         }
5948
5949         /**
5950          * @ngdoc service
5951          * @name $cacheFactory
5952          *
5953          * @description
5954          * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
5955          * them.
5956          *
5957          * ```js
5958          *
5959          *  var cache = $cacheFactory('cacheId');
5960          *  expect($cacheFactory.get('cacheId')).toBe(cache);
5961          *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
5962          *
5963          *  cache.put("key", "value");
5964          *  cache.put("another key", "another value");
5965          *
5966          *  // We've specified no options on creation
5967          *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});
5968          *
5969          * ```
5970          *
5971          *
5972          * @param {string} cacheId Name or id of the newly created cache.
5973          * @param {object=} options Options object that specifies the cache behavior. Properties:
5974          *
5975          *   - `{number=}` `capacity` — turns the cache into LRU cache.
5976          *
5977          * @returns {object} Newly created cache object with the following set of methods:
5978          *
5979          * - `{object}` `info()` — Returns id, size, and options of cache.
5980          * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
5981          *   it.
5982          * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
5983          * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
5984          * - `{void}` `removeAll()` — Removes all cached values.
5985          * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
5986          *
5987          * @example
5988            <example module="cacheExampleApp">
5989              <file name="index.html">
5990                <div ng-controller="CacheController">
5991                  <input ng-model="newCacheKey" placeholder="Key">
5992                  <input ng-model="newCacheValue" placeholder="Value">
5993                  <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
5994
5995                  <p ng-if="keys.length">Cached Values</p>
5996                  <div ng-repeat="key in keys">
5997                    <span ng-bind="key"></span>
5998                    <span>: </span>
5999                    <b ng-bind="cache.get(key)"></b>
6000                  </div>
6001
6002                  <p>Cache Info</p>
6003                  <div ng-repeat="(key, value) in cache.info()">
6004                    <span ng-bind="key"></span>
6005                    <span>: </span>
6006                    <b ng-bind="value"></b>
6007                  </div>
6008                </div>
6009              </file>
6010              <file name="script.js">
6011                angular.module('cacheExampleApp', []).
6012                  controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
6013                    $scope.keys = [];
6014                    $scope.cache = $cacheFactory('cacheId');
6015                    $scope.put = function(key, value) {
6016                      if (angular.isUndefined($scope.cache.get(key))) {
6017                        $scope.keys.push(key);
6018                      }
6019                      $scope.cache.put(key, angular.isUndefined(value) ? null : value);
6020                    };
6021                  }]);
6022              </file>
6023              <file name="style.css">
6024                p {
6025                  margin: 10px 0 3px;
6026                }
6027              </file>
6028            </example>
6029          */
6030         function $CacheFactoryProvider() {
6031
6032           this.$get = function() {
6033             var caches = {};
6034
6035             function cacheFactory(cacheId, options) {
6036               if (cacheId in caches) {
6037                 throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
6038               }
6039
6040               var size = 0,
6041                   stats = extend({}, options, {id: cacheId}),
6042                   data = createMap(),
6043                   capacity = (options && options.capacity) || Number.MAX_VALUE,
6044                   lruHash = createMap(),
6045                   freshEnd = null,
6046                   staleEnd = null;
6047
6048               /**
6049                * @ngdoc type
6050                * @name $cacheFactory.Cache
6051                *
6052                * @description
6053                * A cache object used to store and retrieve data, primarily used by
6054                * {@link $http $http} and the {@link ng.directive:script script} directive to cache
6055                * templates and other data.
6056                *
6057                * ```js
6058                *  angular.module('superCache')
6059                *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {
6060                *      return $cacheFactory('super-cache');
6061                *    }]);
6062                * ```
6063                *
6064                * Example test:
6065                *
6066                * ```js
6067                *  it('should behave like a cache', inject(function(superCache) {
6068                *    superCache.put('key', 'value');
6069                *    superCache.put('another key', 'another value');
6070                *
6071                *    expect(superCache.info()).toEqual({
6072                *      id: 'super-cache',
6073                *      size: 2
6074                *    });
6075                *
6076                *    superCache.remove('another key');
6077                *    expect(superCache.get('another key')).toBeUndefined();
6078                *
6079                *    superCache.removeAll();
6080                *    expect(superCache.info()).toEqual({
6081                *      id: 'super-cache',
6082                *      size: 0
6083                *    });
6084                *  }));
6085                * ```
6086                */
6087               return caches[cacheId] = {
6088
6089                 /**
6090                  * @ngdoc method
6091                  * @name $cacheFactory.Cache#put
6092                  * @kind function
6093                  *
6094                  * @description
6095                  * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
6096                  * retrieved later, and incrementing the size of the cache if the key was not already
6097                  * present in the cache. If behaving like an LRU cache, it will also remove stale
6098                  * entries from the set.
6099                  *
6100                  * It will not insert undefined values into the cache.
6101                  *
6102                  * @param {string} key the key under which the cached data is stored.
6103                  * @param {*} value the value to store alongside the key. If it is undefined, the key
6104                  *    will not be stored.
6105                  * @returns {*} the value stored.
6106                  */
6107                 put: function(key, value) {
6108                   if (isUndefined(value)) return;
6109                   if (capacity < Number.MAX_VALUE) {
6110                     var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
6111
6112                     refresh(lruEntry);
6113                   }
6114
6115                   if (!(key in data)) size++;
6116                   data[key] = value;
6117
6118                   if (size > capacity) {
6119                     this.remove(staleEnd.key);
6120                   }
6121
6122                   return value;
6123                 },
6124
6125                 /**
6126                  * @ngdoc method
6127                  * @name $cacheFactory.Cache#get
6128                  * @kind function
6129                  *
6130                  * @description
6131                  * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
6132                  *
6133                  * @param {string} key the key of the data to be retrieved
6134                  * @returns {*} the value stored.
6135                  */
6136                 get: function(key) {
6137                   if (capacity < Number.MAX_VALUE) {
6138                     var lruEntry = lruHash[key];
6139
6140                     if (!lruEntry) return;
6141
6142                     refresh(lruEntry);
6143                   }
6144
6145                   return data[key];
6146                 },
6147
6148
6149                 /**
6150                  * @ngdoc method
6151                  * @name $cacheFactory.Cache#remove
6152                  * @kind function
6153                  *
6154                  * @description
6155                  * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
6156                  *
6157                  * @param {string} key the key of the entry to be removed
6158                  */
6159                 remove: function(key) {
6160                   if (capacity < Number.MAX_VALUE) {
6161                     var lruEntry = lruHash[key];
6162
6163                     if (!lruEntry) return;
6164
6165                     if (lruEntry == freshEnd) freshEnd = lruEntry.p;
6166                     if (lruEntry == staleEnd) staleEnd = lruEntry.n;
6167                     link(lruEntry.n,lruEntry.p);
6168
6169                     delete lruHash[key];
6170                   }
6171
6172                   if (!(key in data)) return;
6173
6174                   delete data[key];
6175                   size--;
6176                 },
6177
6178
6179                 /**
6180                  * @ngdoc method
6181                  * @name $cacheFactory.Cache#removeAll
6182                  * @kind function
6183                  *
6184                  * @description
6185                  * Clears the cache object of any entries.
6186                  */
6187                 removeAll: function() {
6188                   data = createMap();
6189                   size = 0;
6190                   lruHash = createMap();
6191                   freshEnd = staleEnd = null;
6192                 },
6193
6194
6195                 /**
6196                  * @ngdoc method
6197                  * @name $cacheFactory.Cache#destroy
6198                  * @kind function
6199                  *
6200                  * @description
6201                  * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
6202                  * removing it from the {@link $cacheFactory $cacheFactory} set.
6203                  */
6204                 destroy: function() {
6205                   data = null;
6206                   stats = null;
6207                   lruHash = null;
6208                   delete caches[cacheId];
6209                 },
6210
6211
6212                 /**
6213                  * @ngdoc method
6214                  * @name $cacheFactory.Cache#info
6215                  * @kind function
6216                  *
6217                  * @description
6218                  * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
6219                  *
6220                  * @returns {object} an object with the following properties:
6221                  *   <ul>
6222                  *     <li>**id**: the id of the cache instance</li>
6223                  *     <li>**size**: the number of entries kept in the cache instance</li>
6224                  *     <li>**...**: any additional properties from the options object when creating the
6225                  *       cache.</li>
6226                  *   </ul>
6227                  */
6228                 info: function() {
6229                   return extend({}, stats, {size: size});
6230                 }
6231               };
6232
6233
6234               /**
6235                * makes the `entry` the freshEnd of the LRU linked list
6236                */
6237               function refresh(entry) {
6238                 if (entry != freshEnd) {
6239                   if (!staleEnd) {
6240                     staleEnd = entry;
6241                   } else if (staleEnd == entry) {
6242                     staleEnd = entry.n;
6243                   }
6244
6245                   link(entry.n, entry.p);
6246                   link(entry, freshEnd);
6247                   freshEnd = entry;
6248                   freshEnd.n = null;
6249                 }
6250               }
6251
6252
6253               /**
6254                * bidirectionally links two entries of the LRU linked list
6255                */
6256               function link(nextEntry, prevEntry) {
6257                 if (nextEntry != prevEntry) {
6258                   if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
6259                   if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
6260                 }
6261               }
6262             }
6263
6264
6265           /**
6266            * @ngdoc method
6267            * @name $cacheFactory#info
6268            *
6269            * @description
6270            * Get information about all the caches that have been created
6271            *
6272            * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
6273            */
6274             cacheFactory.info = function() {
6275               var info = {};
6276               forEach(caches, function(cache, cacheId) {
6277                 info[cacheId] = cache.info();
6278               });
6279               return info;
6280             };
6281
6282
6283           /**
6284            * @ngdoc method
6285            * @name $cacheFactory#get
6286            *
6287            * @description
6288            * Get access to a cache object by the `cacheId` used when it was created.
6289            *
6290            * @param {string} cacheId Name or id of a cache to access.
6291            * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
6292            */
6293             cacheFactory.get = function(cacheId) {
6294               return caches[cacheId];
6295             };
6296
6297
6298             return cacheFactory;
6299           };
6300         }
6301
6302         /**
6303          * @ngdoc service
6304          * @name $templateCache
6305          *
6306          * @description
6307          * The first time a template is used, it is loaded in the template cache for quick retrieval. You
6308          * can load templates directly into the cache in a `script` tag, or by consuming the
6309          * `$templateCache` service directly.
6310          *
6311          * Adding via the `script` tag:
6312          *
6313          * ```html
6314          *   <script type="text/ng-template" id="templateId.html">
6315          *     <p>This is the content of the template</p>
6316          *   </script>
6317          * ```
6318          *
6319          * **Note:** the `script` tag containing the template does not need to be included in the `head` of
6320          * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
6321          * element with ng-app attribute), otherwise the template will be ignored.
6322          *
6323          * Adding via the `$templateCache` service:
6324          *
6325          * ```js
6326          * var myApp = angular.module('myApp', []);
6327          * myApp.run(function($templateCache) {
6328          *   $templateCache.put('templateId.html', 'This is the content of the template');
6329          * });
6330          * ```
6331          *
6332          * To retrieve the template later, simply use it in your HTML:
6333          * ```html
6334          * <div ng-include=" 'templateId.html' "></div>
6335          * ```
6336          *
6337          * or get it via Javascript:
6338          * ```js
6339          * $templateCache.get('templateId.html')
6340          * ```
6341          *
6342          * See {@link ng.$cacheFactory $cacheFactory}.
6343          *
6344          */
6345         function $TemplateCacheProvider() {
6346           this.$get = ['$cacheFactory', function($cacheFactory) {
6347             return $cacheFactory('templates');
6348           }];
6349         }
6350
6351         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
6352          *     Any commits to this file should be reviewed with security in mind.  *
6353          *   Changes to this file can potentially create security vulnerabilities. *
6354          *          An approval from 2 Core members with history of modifying      *
6355          *                         this file is required.                          *
6356          *                                                                         *
6357          *  Does the change somehow allow for arbitrary javascript to be executed? *
6358          *    Or allows for someone to change the prototype of built-in objects?   *
6359          *     Or gives undesired access to variables likes document or window?    *
6360          * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6361
6362         /* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
6363          *
6364          * DOM-related variables:
6365          *
6366          * - "node" - DOM Node
6367          * - "element" - DOM Element or Node
6368          * - "$node" or "$element" - jqLite-wrapped node or element
6369          *
6370          *
6371          * Compiler related stuff:
6372          *
6373          * - "linkFn" - linking fn of a single directive
6374          * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
6375          * - "childLinkFn" -  function that aggregates all linking fns for child nodes of a particular node
6376          * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
6377          */
6378
6379
6380         /**
6381          * @ngdoc service
6382          * @name $compile
6383          * @kind function
6384          *
6385          * @description
6386          * Compiles an HTML string or DOM into a template and produces a template function, which
6387          * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
6388          *
6389          * The compilation is a process of walking the DOM tree and matching DOM elements to
6390          * {@link ng.$compileProvider#directive directives}.
6391          *
6392          * <div class="alert alert-warning">
6393          * **Note:** This document is an in-depth reference of all directive options.
6394          * For a gentle introduction to directives with examples of common use cases,
6395          * see the {@link guide/directive directive guide}.
6396          * </div>
6397          *
6398          * ## Comprehensive Directive API
6399          *
6400          * There are many different options for a directive.
6401          *
6402          * The difference resides in the return value of the factory function.
6403          * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
6404          * or just the `postLink` function (all other properties will have the default values).
6405          *
6406          * <div class="alert alert-success">
6407          * **Best Practice:** It's recommended to use the "directive definition object" form.
6408          * </div>
6409          *
6410          * Here's an example directive declared with a Directive Definition Object:
6411          *
6412          * ```js
6413          *   var myModule = angular.module(...);
6414          *
6415          *   myModule.directive('directiveName', function factory(injectables) {
6416          *     var directiveDefinitionObject = {
6417          *       priority: 0,
6418          *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },
6419          *       // or
6420          *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
6421          *       transclude: false,
6422          *       restrict: 'A',
6423          *       templateNamespace: 'html',
6424          *       scope: false,
6425          *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
6426          *       controllerAs: 'stringIdentifier',
6427          *       bindToController: false,
6428          *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
6429          *       compile: function compile(tElement, tAttrs, transclude) {
6430          *         return {
6431          *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },
6432          *           post: function postLink(scope, iElement, iAttrs, controller) { ... }
6433          *         }
6434          *         // or
6435          *         // return function postLink( ... ) { ... }
6436          *       },
6437          *       // or
6438          *       // link: {
6439          *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },
6440          *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }
6441          *       // }
6442          *       // or
6443          *       // link: function postLink( ... ) { ... }
6444          *     };
6445          *     return directiveDefinitionObject;
6446          *   });
6447          * ```
6448          *
6449          * <div class="alert alert-warning">
6450          * **Note:** Any unspecified options will use the default value. You can see the default values below.
6451          * </div>
6452          *
6453          * Therefore the above can be simplified as:
6454          *
6455          * ```js
6456          *   var myModule = angular.module(...);
6457          *
6458          *   myModule.directive('directiveName', function factory(injectables) {
6459          *     var directiveDefinitionObject = {
6460          *       link: function postLink(scope, iElement, iAttrs) { ... }
6461          *     };
6462          *     return directiveDefinitionObject;
6463          *     // or
6464          *     // return function postLink(scope, iElement, iAttrs) { ... }
6465          *   });
6466          * ```
6467          *
6468          *
6469          *
6470          * ### Directive Definition Object
6471          *
6472          * The directive definition object provides instructions to the {@link ng.$compile
6473          * compiler}. The attributes are:
6474          *
6475          * #### `multiElement`
6476          * When this property is set to true, the HTML compiler will collect DOM nodes between
6477          * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
6478          * together as the directive elements. It is recommended that this feature be used on directives
6479          * which are not strictly behavioural (such as {@link ngClick}), and which
6480          * do not manipulate or replace child nodes (such as {@link ngInclude}).
6481          *
6482          * #### `priority`
6483          * When there are multiple directives defined on a single DOM element, sometimes it
6484          * is necessary to specify the order in which the directives are applied. The `priority` is used
6485          * to sort the directives before their `compile` functions get called. Priority is defined as a
6486          * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
6487          * are also run in priority order, but post-link functions are run in reverse order. The order
6488          * of directives with the same priority is undefined. The default priority is `0`.
6489          *
6490          * #### `terminal`
6491          * If set to true then the current `priority` will be the last set of directives
6492          * which will execute (any directives at the current priority will still execute
6493          * as the order of execution on same `priority` is undefined). Note that expressions
6494          * and other directives used in the directive's template will also be excluded from execution.
6495          *
6496          * #### `scope`
6497          * The scope property can be `true`, an object or a falsy value:
6498          *
6499          * * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
6500          *
6501          * * **`true`:** A new child scope that prototypically inherits from its parent will be created for
6502          * the directive's element. If multiple directives on the same element request a new scope,
6503          * only one new scope is created. The new scope rule does not apply for the root of the template
6504          * since the root of the template always gets a new scope.
6505          *
6506          * * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
6507          * 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
6508          * scope. This is useful when creating reusable components, which should not accidentally read or modify
6509          * data in the parent scope.
6510          *
6511          * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
6512          * directive's element. These local properties are useful for aliasing values for templates. The keys in
6513          * the object hash map to the name of the property on the isolate scope; the values define how the property
6514          * is bound to the parent scope, via matching attributes on the directive's element:
6515          *
6516          * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
6517          *   always a string since DOM attributes are strings. If no `attr` name is specified  then the
6518          *   attribute name is assumed to be the same as the local name.
6519          *   Given `<widget my-attr="hello {{name}}">` and widget definition
6520          *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
6521          *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
6522          *   `localName` property on the widget scope. The `name` is read from the parent scope (not
6523          *   component scope).
6524          *
6525          * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
6526          *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`
6527          *   name is specified then the attribute name is assumed to be the same as the local name.
6528          *   Given `<widget my-attr="parentModel">` and widget definition of
6529          *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
6530          *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
6531          *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
6532          *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
6533          *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
6534          *   you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
6535          *   `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
6536          *
6537          * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
6538          *   If no `attr` name is specified then the attribute name is assumed to be the same as the
6539          *   local name. Given `<widget my-attr="count = count + value">` and widget definition of
6540          *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
6541          *   a function wrapper for the `count = count + value` expression. Often it's desirable to
6542          *   pass data from the isolated scope via an expression to the parent scope, this can be
6543          *   done by passing a map of local variable names and values into the expression wrapper fn.
6544          *   For example, if the expression is `increment(amount)` then we can specify the amount value
6545          *   by calling the `localFn` as `localFn({amount: 22})`.
6546          *
6547          * In general it's possible to apply more than one directive to one element, but there might be limitations
6548          * depending on the type of scope required by the directives. The following points will help explain these limitations.
6549          * For simplicity only two directives are taken into account, but it is also applicable for several directives:
6550          *
6551          * * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope
6552          * * **child scope** + **no scope** =>  Both directives will share one single child scope
6553          * * **child scope** + **child scope** =>  Both directives will share one single child scope
6554          * * **isolated scope** + **no scope** =>  The isolated directive will use it's own created isolated scope. The other directive will use
6555          * its parent's scope
6556          * * **isolated scope** + **child scope** =>  **Won't work!** Only one scope can be related to one element. Therefore these directives cannot
6557          * be applied to the same element.
6558          * * **isolated scope** + **isolated scope**  =>  **Won't work!** Only one scope can be related to one element. Therefore these directives
6559          * cannot be applied to the same element.
6560          *
6561          *
6562          * #### `bindToController`
6563          * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
6564          * allow a component to have its properties bound to the controller, rather than to scope. When the controller
6565          * is instantiated, the initial values of the isolate scope bindings are already available.
6566          *
6567          * #### `controller`
6568          * Controller constructor function. The controller is instantiated before the
6569          * pre-linking phase and can be accessed by other directives (see
6570          * `require` attribute). This allows the directives to communicate with each other and augment
6571          * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
6572          *
6573          * * `$scope` - Current scope associated with the element
6574          * * `$element` - Current element
6575          * * `$attrs` - Current attributes object for the element
6576          * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
6577          *   `function([scope], cloneLinkingFn, futureParentElement)`.
6578          *    * `scope`: optional argument to override the scope.
6579          *    * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.
6580          *    * `futureParentElement`:
6581          *        * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
6582          *        * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
6583          *        * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
6584          *          and when the `cloneLinkinFn` is passed,
6585          *          as those elements need to created and cloned in a special way when they are defined outside their
6586          *          usual containers (e.g. like `<svg>`).
6587          *        * See also the `directive.templateNamespace` property.
6588          *
6589          *
6590          * #### `require`
6591          * Require another directive and inject its controller as the fourth argument to the linking function. The
6592          * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
6593          * injected argument will be an array in corresponding order. If no such directive can be
6594          * found, or if the directive does not have a controller, then an error is raised (unless no link function
6595          * is specified, in which case error checking is skipped). The name can be prefixed with:
6596          *
6597          * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
6598          * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
6599          * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
6600          * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.
6601          * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
6602          *   `null` to the `link` fn if not found.
6603          * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass
6604          *   `null` to the `link` fn if not found.
6605          *
6606          *
6607          * #### `controllerAs`
6608          * Identifier name for a reference to the controller in the directive's scope.
6609          * This allows the controller to be referenced from the directive template. This is especially
6610          * useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible
6611          * to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the
6612          * `controllerAs` reference might overwrite a property that already exists on the parent scope.
6613          *
6614          *
6615          * #### `restrict`
6616          * String of subset of `EACM` which restricts the directive to a specific directive
6617          * declaration style. If omitted, the defaults (elements and attributes) are used.
6618          *
6619          * * `E` - Element name (default): `<my-directive></my-directive>`
6620          * * `A` - Attribute (default): `<div my-directive="exp"></div>`
6621          * * `C` - Class: `<div class="my-directive: exp;"></div>`
6622          * * `M` - Comment: `<!-- directive: my-directive exp -->`
6623          *
6624          *
6625          * #### `templateNamespace`
6626          * String representing the document type used by the markup in the template.
6627          * AngularJS needs this information as those elements need to be created and cloned
6628          * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.
6629          *
6630          * * `html` - All root nodes in the template are HTML. Root nodes may also be
6631          *   top-level elements such as `<svg>` or `<math>`.
6632          * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).
6633          * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).
6634          *
6635          * If no `templateNamespace` is specified, then the namespace is considered to be `html`.
6636          *
6637          * #### `template`
6638          * HTML markup that may:
6639          * * Replace the contents of the directive's element (default).
6640          * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
6641          * * Wrap the contents of the directive's element (if `transclude` is true).
6642          *
6643          * Value may be:
6644          *
6645          * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
6646          * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
6647          *   function api below) and returns a string value.
6648          *
6649          *
6650          * #### `templateUrl`
6651          * This is similar to `template` but the template is loaded from the specified URL, asynchronously.
6652          *
6653          * Because template loading is asynchronous the compiler will suspend compilation of directives on that element
6654          * for later when the template has been resolved.  In the meantime it will continue to compile and link
6655          * sibling and parent elements as though this element had not contained any directives.
6656          *
6657          * The compiler does not suspend the entire compilation to wait for templates to be loaded because this
6658          * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the
6659          * case when only one deeply nested directive has `templateUrl`.
6660          *
6661          * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
6662          *
6663          * You can specify `templateUrl` as a string representing the URL or as a function which takes two
6664          * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
6665          * a string value representing the url.  In either case, the template URL is passed through {@link
6666          * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
6667          *
6668          *
6669          * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
6670          * specify what the template should replace. Defaults to `false`.
6671          *
6672          * * `true` - the template will replace the directive's element.
6673          * * `false` - the template will replace the contents of the directive's element.
6674          *
6675          * The replacement process migrates all of the attributes / classes from the old element to the new
6676          * one. See the {@link guide/directive#template-expanding-directive
6677          * Directives Guide} for an example.
6678          *
6679          * There are very few scenarios where element replacement is required for the application function,
6680          * the main one being reusable custom components that are used within SVG contexts
6681          * (because SVG doesn't work with custom elements in the DOM tree).
6682          *
6683          * #### `transclude`
6684          * Extract the contents of the element where the directive appears and make it available to the directive.
6685          * The contents are compiled and provided to the directive as a **transclusion function**. See the
6686          * {@link $compile#transclusion Transclusion} section below.
6687          *
6688          * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
6689          * directive's element or the entire element:
6690          *
6691          * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
6692          * * `'element'` - transclude the whole of the directive's element including any directives on this
6693          *   element that defined at a lower priority than this directive. When used, the `template`
6694          *   property is ignored.
6695          *
6696          *
6697          * #### `compile`
6698          *
6699          * ```js
6700          *   function compile(tElement, tAttrs, transclude) { ... }
6701          * ```
6702          *
6703          * The compile function deals with transforming the template DOM. Since most directives do not do
6704          * template transformation, it is not used often. The compile function takes the following arguments:
6705          *
6706          *   * `tElement` - template element - The element where the directive has been declared. It is
6707          *     safe to do template transformation on the element and child elements only.
6708          *
6709          *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
6710          *     between all directive compile functions.
6711          *
6712          *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
6713          *
6714          * <div class="alert alert-warning">
6715          * **Note:** The template instance and the link instance may be different objects if the template has
6716          * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
6717          * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
6718          * should be done in a linking function rather than in a compile function.
6719          * </div>
6720
6721          * <div class="alert alert-warning">
6722          * **Note:** The compile function cannot handle directives that recursively use themselves in their
6723          * own templates or compile functions. Compiling these directives results in an infinite loop and a
6724          * stack overflow errors.
6725          *
6726          * This can be avoided by manually using $compile in the postLink function to imperatively compile
6727          * a directive's template instead of relying on automatic template compilation via `template` or
6728          * `templateUrl` declaration or manual compilation inside the compile function.
6729          * </div>
6730          *
6731          * <div class="alert alert-danger">
6732          * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
6733          *   e.g. does not know about the right outer scope. Please use the transclude function that is passed
6734          *   to the link function instead.
6735          * </div>
6736
6737          * A compile function can have a return value which can be either a function or an object.
6738          *
6739          * * returning a (post-link) function - is equivalent to registering the linking function via the
6740          *   `link` property of the config object when the compile function is empty.
6741          *
6742          * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
6743          *   control when a linking function should be called during the linking phase. See info about
6744          *   pre-linking and post-linking functions below.
6745          *
6746          *
6747          * #### `link`
6748          * This property is used only if the `compile` property is not defined.
6749          *
6750          * ```js
6751          *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
6752          * ```
6753          *
6754          * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
6755          * executed after the template has been cloned. This is where most of the directive logic will be
6756          * put.
6757          *
6758          *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
6759          *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.
6760          *
6761          *   * `iElement` - instance element - The element where the directive is to be used. It is safe to
6762          *     manipulate the children of the element only in `postLink` function since the children have
6763          *     already been linked.
6764          *
6765          *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
6766          *     between all directive linking functions.
6767          *
6768          *   * `controller` - the directive's required controller instance(s) - Instances are shared
6769          *     among all directives, which allows the directives to use the controllers as a communication
6770          *     channel. The exact value depends on the directive's `require` property:
6771          *       * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one
6772          *       * `string`: the controller instance
6773          *       * `array`: array of controller instances
6774          *
6775          *     If a required controller cannot be found, and it is optional, the instance is `null`,
6776          *     otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
6777          *
6778          *     Note that you can also require the directive's own controller - it will be made available like
6779          *     any other controller.
6780          *
6781          *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
6782          *     This is the same as the `$transclude`
6783          *     parameter of directive controllers, see there for details.
6784          *     `function([scope], cloneLinkingFn, futureParentElement)`.
6785          *
6786          * #### Pre-linking function
6787          *
6788          * Executed before the child elements are linked. Not safe to do DOM transformation since the
6789          * compiler linking function will fail to locate the correct elements for linking.
6790          *
6791          * #### Post-linking function
6792          *
6793          * Executed after the child elements are linked.
6794          *
6795          * Note that child elements that contain `templateUrl` directives will not have been compiled
6796          * and linked since they are waiting for their template to load asynchronously and their own
6797          * compilation and linking has been suspended until that occurs.
6798          *
6799          * It is safe to do DOM transformation in the post-linking function on elements that are not waiting
6800          * for their async templates to be resolved.
6801          *
6802          *
6803          * ### Transclusion
6804          *
6805          * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
6806          * copying them to another part of the DOM, while maintaining their connection to the original AngularJS
6807          * scope from where they were taken.
6808          *
6809          * Transclusion is used (often with {@link ngTransclude}) to insert the
6810          * original contents of a directive's element into a specified place in the template of the directive.
6811          * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded
6812          * content has access to the properties on the scope from which it was taken, even if the directive
6813          * has isolated scope.
6814          * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.
6815          *
6816          * This makes it possible for the widget to have private state for its template, while the transcluded
6817          * content has access to its originating scope.
6818          *
6819          * <div class="alert alert-warning">
6820          * **Note:** When testing an element transclude directive you must not place the directive at the root of the
6821          * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
6822          * Testing Transclusion Directives}.
6823          * </div>
6824          *
6825          * #### Transclusion Functions
6826          *
6827          * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
6828          * function** to the directive's `link` function and `controller`. This transclusion function is a special
6829          * **linking function** that will return the compiled contents linked to a new transclusion scope.
6830          *
6831          * <div class="alert alert-info">
6832          * If you are just using {@link ngTransclude} then you don't need to worry about this function, since
6833          * ngTransclude will deal with it for us.
6834          * </div>
6835          *
6836          * If you want to manually control the insertion and removal of the transcluded content in your directive
6837          * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
6838          * object that contains the compiled DOM, which is linked to the correct transclusion scope.
6839          *
6840          * When you call a transclusion function you can pass in a **clone attach function**. This function accepts
6841          * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
6842          * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
6843          *
6844          * <div class="alert alert-info">
6845          * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
6846          * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
6847          * </div>
6848          *
6849          * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone
6850          * attach function**:
6851          *
6852          * ```js
6853          * var transcludedContent, transclusionScope;
6854          *
6855          * $transclude(function(clone, scope) {
6856          *   element.append(clone);
6857          *   transcludedContent = clone;
6858          *   transclusionScope = scope;
6859          * });
6860          * ```
6861          *
6862          * Later, if you want to remove the transcluded content from your DOM then you should also destroy the
6863          * associated transclusion scope:
6864          *
6865          * ```js
6866          * transcludedContent.remove();
6867          * transclusionScope.$destroy();
6868          * ```
6869          *
6870          * <div class="alert alert-info">
6871          * **Best Practice**: if you intend to add and remove transcluded content manually in your directive
6872          * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it),
6873          * then you are also responsible for calling `$destroy` on the transclusion scope.
6874          * </div>
6875          *
6876          * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
6877          * automatically destroy their transluded clones as necessary so you do not need to worry about this if
6878          * you are simply using {@link ngTransclude} to inject the transclusion into your directive.
6879          *
6880          *
6881          * #### Transclusion Scopes
6882          *
6883          * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion
6884          * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed
6885          * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it
6886          * was taken.
6887          *
6888          * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look
6889          * like this:
6890          *
6891          * ```html
6892          * <div ng-app>
6893          *   <div isolate>
6894          *     <div transclusion>
6895          *     </div>
6896          *   </div>
6897          * </div>
6898          * ```
6899          *
6900          * The `$parent` scope hierarchy will look like this:
6901          *
6902          * ```
6903          * - $rootScope
6904          *   - isolate
6905          *     - transclusion
6906          * ```
6907          *
6908          * but the scopes will inherit prototypically from different scopes to their `$parent`.
6909          *
6910          * ```
6911          * - $rootScope
6912          *   - transclusion
6913          * - isolate
6914          * ```
6915          *
6916          *
6917          * ### Attributes
6918          *
6919          * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
6920          * `link()` or `compile()` functions. It has a variety of uses.
6921          *
6922          * accessing *Normalized attribute names:*
6923          * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
6924          * the attributes object allows for normalized access to
6925          *   the attributes.
6926          *
6927          * * *Directive inter-communication:* All directives share the same instance of the attributes
6928          *   object which allows the directives to use the attributes object as inter directive
6929          *   communication.
6930          *
6931          * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
6932          *   allowing other directives to read the interpolated value.
6933          *
6934          * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
6935          *   that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
6936          *   the only way to easily get the actual value because during the linking phase the interpolation
6937          *   hasn't been evaluated yet and so the value is at this time set to `undefined`.
6938          *
6939          * ```js
6940          * function linkingFn(scope, elm, attrs, ctrl) {
6941          *   // get the attribute value
6942          *   console.log(attrs.ngModel);
6943          *
6944          *   // change the attribute
6945          *   attrs.$set('ngModel', 'new value');
6946          *
6947          *   // observe changes to interpolated attribute
6948          *   attrs.$observe('ngModel', function(value) {
6949          *     console.log('ngModel has changed value to ' + value);
6950          *   });
6951          * }
6952          * ```
6953          *
6954          * ## Example
6955          *
6956          * <div class="alert alert-warning">
6957          * **Note**: Typically directives are registered with `module.directive`. The example below is
6958          * to illustrate how `$compile` works.
6959          * </div>
6960          *
6961          <example module="compileExample">
6962            <file name="index.html">
6963             <script>
6964               angular.module('compileExample', [], function($compileProvider) {
6965                 // configure new 'compile' directive by passing a directive
6966                 // factory function. The factory function injects the '$compile'
6967                 $compileProvider.directive('compile', function($compile) {
6968                   // directive factory creates a link function
6969                   return function(scope, element, attrs) {
6970                     scope.$watch(
6971                       function(scope) {
6972                          // watch the 'compile' expression for changes
6973                         return scope.$eval(attrs.compile);
6974                       },
6975                       function(value) {
6976                         // when the 'compile' expression changes
6977                         // assign it into the current DOM
6978                         element.html(value);
6979
6980                         // compile the new DOM and link it to the current
6981                         // scope.
6982                         // NOTE: we only compile .childNodes so that
6983                         // we don't get into infinite loop compiling ourselves
6984                         $compile(element.contents())(scope);
6985                       }
6986                     );
6987                   };
6988                 });
6989               })
6990               .controller('GreeterController', ['$scope', function($scope) {
6991                 $scope.name = 'Angular';
6992                 $scope.html = 'Hello {{name}}';
6993               }]);
6994             </script>
6995             <div ng-controller="GreeterController">
6996               <input ng-model="name"> <br/>
6997               <textarea ng-model="html"></textarea> <br/>
6998               <div compile="html"></div>
6999             </div>
7000            </file>
7001            <file name="protractor.js" type="protractor">
7002              it('should auto compile', function() {
7003                var textarea = $('textarea');
7004                var output = $('div[compile]');
7005                // The initial state reads 'Hello Angular'.
7006                expect(output.getText()).toBe('Hello Angular');
7007                textarea.clear();
7008                textarea.sendKeys('{{name}}!');
7009                expect(output.getText()).toBe('Angular!');
7010              });
7011            </file>
7012          </example>
7013
7014          *
7015          *
7016          * @param {string|DOMElement} element Element or HTML string to compile into a template function.
7017          * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.
7018          *
7019          * <div class="alert alert-danger">
7020          * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it
7021          *   e.g. will not use the right outer scope. Please pass the transclude function as a
7022          *   `parentBoundTranscludeFn` to the link function instead.
7023          * </div>
7024          *
7025          * @param {number} maxPriority only apply directives lower than given priority (Only effects the
7026          *                 root element(s), not their children)
7027          * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template
7028          * (a DOM element/tree) to a scope. Where:
7029          *
7030          *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
7031          *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
7032          *  `template` and call the `cloneAttachFn` function allowing the caller to attach the
7033          *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
7034          *  called as: <br/> `cloneAttachFn(clonedElement, scope)` where:
7035          *
7036          *      * `clonedElement` - is a clone of the original `element` passed into the compiler.
7037          *      * `scope` - is the current scope with which the linking function is working with.
7038          *
7039          *  * `options` - An optional object hash with linking options. If `options` is provided, then the following
7040          *  keys may be used to control linking behavior:
7041          *
7042          *      * `parentBoundTranscludeFn` - the transclude function made available to
7043          *        directives; if given, it will be passed through to the link functions of
7044          *        directives found in `element` during compilation.
7045          *      * `transcludeControllers` - an object hash with keys that map controller names
7046          *        to controller instances; if given, it will make the controllers
7047          *        available to directives.
7048          *      * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
7049          *        the cloned elements; only needed for transcludes that are allowed to contain non html
7050          *        elements (e.g. SVG elements). See also the directive.controller property.
7051          *
7052          * Calling the linking function returns the element of the template. It is either the original
7053          * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
7054          *
7055          * After linking the view is not updated until after a call to $digest which typically is done by
7056          * Angular automatically.
7057          *
7058          * If you need access to the bound view, there are two ways to do it:
7059          *
7060          * - If you are not asking the linking function to clone the template, create the DOM element(s)
7061          *   before you send them to the compiler and keep this reference around.
7062          *   ```js
7063          *     var element = $compile('<p>{{total}}</p>')(scope);
7064          *   ```
7065          *
7066          * - if on the other hand, you need the element to be cloned, the view reference from the original
7067          *   example would not point to the clone, but rather to the original template that was cloned. In
7068          *   this case, you can access the clone via the cloneAttachFn:
7069          *   ```js
7070          *     var templateElement = angular.element('<p>{{total}}</p>'),
7071          *         scope = ....;
7072          *
7073          *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
7074          *       //attach the clone to DOM document at the right place
7075          *     });
7076          *
7077          *     //now we have reference to the cloned DOM via `clonedElement`
7078          *   ```
7079          *
7080          *
7081          * For information on how the compiler works, see the
7082          * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
7083          */
7084
7085         var $compileMinErr = minErr('$compile');
7086
7087         /**
7088          * @ngdoc provider
7089          * @name $compileProvider
7090          *
7091          * @description
7092          */
7093         $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
7094         function $CompileProvider($provide, $$sanitizeUriProvider) {
7095           var hasDirectives = {},
7096               Suffix = 'Directive',
7097               COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
7098               CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
7099               ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
7100               REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
7101
7102           // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
7103           // The assumption is that future DOM event attribute names will begin with
7104           // 'on' and be composed of only English letters.
7105           var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
7106
7107           function parseIsolateBindings(scope, directiveName, isController) {
7108             var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
7109
7110             var bindings = {};
7111
7112             forEach(scope, function(definition, scopeName) {
7113               var match = definition.match(LOCAL_REGEXP);
7114
7115               if (!match) {
7116                 throw $compileMinErr('iscp',
7117                     "Invalid {3} for directive '{0}'." +
7118                     " Definition: {... {1}: '{2}' ...}",
7119                     directiveName, scopeName, definition,
7120                     (isController ? "controller bindings definition" :
7121                     "isolate scope definition"));
7122               }
7123
7124               bindings[scopeName] = {
7125                 mode: match[1][0],
7126                 collection: match[2] === '*',
7127                 optional: match[3] === '?',
7128                 attrName: match[4] || scopeName
7129               };
7130             });
7131
7132             return bindings;
7133           }
7134
7135           function parseDirectiveBindings(directive, directiveName) {
7136             var bindings = {
7137               isolateScope: null,
7138               bindToController: null
7139             };
7140             if (isObject(directive.scope)) {
7141               if (directive.bindToController === true) {
7142                 bindings.bindToController = parseIsolateBindings(directive.scope,
7143                                                                  directiveName, true);
7144                 bindings.isolateScope = {};
7145               } else {
7146                 bindings.isolateScope = parseIsolateBindings(directive.scope,
7147                                                              directiveName, false);
7148               }
7149             }
7150             if (isObject(directive.bindToController)) {
7151               bindings.bindToController =
7152                   parseIsolateBindings(directive.bindToController, directiveName, true);
7153             }
7154             if (isObject(bindings.bindToController)) {
7155               var controller = directive.controller;
7156               var controllerAs = directive.controllerAs;
7157               if (!controller) {
7158                 // There is no controller, there may or may not be a controllerAs property
7159                 throw $compileMinErr('noctrl',
7160                       "Cannot bind to controller without directive '{0}'s controller.",
7161                       directiveName);
7162               } else if (!identifierForController(controller, controllerAs)) {
7163                 // There is a controller, but no identifier or controllerAs property
7164                 throw $compileMinErr('noident',
7165                       "Cannot bind to controller without identifier for directive '{0}'.",
7166                       directiveName);
7167               }
7168             }
7169             return bindings;
7170           }
7171
7172           function assertValidDirectiveName(name) {
7173             var letter = name.charAt(0);
7174             if (!letter || letter !== lowercase(letter)) {
7175               throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
7176             }
7177             if (name !== name.trim()) {
7178               throw $compileMinErr('baddir',
7179                     "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
7180                     name);
7181             }
7182           }
7183
7184           /**
7185            * @ngdoc method
7186            * @name $compileProvider#directive
7187            * @kind function
7188            *
7189            * @description
7190            * Register a new directive with the compiler.
7191            *
7192            * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
7193            *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the
7194            *    names and the values are the factories.
7195            * @param {Function|Array} directiveFactory An injectable directive factory function. See
7196            *    {@link guide/directive} for more info.
7197            * @returns {ng.$compileProvider} Self for chaining.
7198            */
7199            this.directive = function registerDirective(name, directiveFactory) {
7200             assertNotHasOwnProperty(name, 'directive');
7201             if (isString(name)) {
7202               assertValidDirectiveName(name);
7203               assertArg(directiveFactory, 'directiveFactory');
7204               if (!hasDirectives.hasOwnProperty(name)) {
7205                 hasDirectives[name] = [];
7206                 $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
7207                   function($injector, $exceptionHandler) {
7208                     var directives = [];
7209                     forEach(hasDirectives[name], function(directiveFactory, index) {
7210                       try {
7211                         var directive = $injector.invoke(directiveFactory);
7212                         if (isFunction(directive)) {
7213                           directive = { compile: valueFn(directive) };
7214                         } else if (!directive.compile && directive.link) {
7215                           directive.compile = valueFn(directive.link);
7216                         }
7217                         directive.priority = directive.priority || 0;
7218                         directive.index = index;
7219                         directive.name = directive.name || name;
7220                         directive.require = directive.require || (directive.controller && directive.name);
7221                         directive.restrict = directive.restrict || 'EA';
7222                         var bindings = directive.$$bindings =
7223                             parseDirectiveBindings(directive, directive.name);
7224                         if (isObject(bindings.isolateScope)) {
7225                           directive.$$isolateBindings = bindings.isolateScope;
7226                         }
7227                         directive.$$moduleName = directiveFactory.$$moduleName;
7228                         directives.push(directive);
7229                       } catch (e) {
7230                         $exceptionHandler(e);
7231                       }
7232                     });
7233                     return directives;
7234                   }]);
7235               }
7236               hasDirectives[name].push(directiveFactory);
7237             } else {
7238               forEach(name, reverseParams(registerDirective));
7239             }
7240             return this;
7241           };
7242
7243
7244           /**
7245            * @ngdoc method
7246            * @name $compileProvider#aHrefSanitizationWhitelist
7247            * @kind function
7248            *
7249            * @description
7250            * Retrieves or overrides the default regular expression that is used for whitelisting of safe
7251            * urls during a[href] sanitization.
7252            *
7253            * The sanitization is a security measure aimed at preventing XSS attacks via html links.
7254            *
7255            * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
7256            * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
7257            * regular expression. If a match is found, the original url is written into the dom. Otherwise,
7258            * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
7259            *
7260            * @param {RegExp=} regexp New regexp to whitelist urls with.
7261            * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
7262            *    chaining otherwise.
7263            */
7264           this.aHrefSanitizationWhitelist = function(regexp) {
7265             if (isDefined(regexp)) {
7266               $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
7267               return this;
7268             } else {
7269               return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
7270             }
7271           };
7272
7273
7274           /**
7275            * @ngdoc method
7276            * @name $compileProvider#imgSrcSanitizationWhitelist
7277            * @kind function
7278            *
7279            * @description
7280            * Retrieves or overrides the default regular expression that is used for whitelisting of safe
7281            * urls during img[src] sanitization.
7282            *
7283            * The sanitization is a security measure aimed at prevent XSS attacks via html links.
7284            *
7285            * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
7286            * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
7287            * regular expression. If a match is found, the original url is written into the dom. Otherwise,
7288            * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
7289            *
7290            * @param {RegExp=} regexp New regexp to whitelist urls with.
7291            * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
7292            *    chaining otherwise.
7293            */
7294           this.imgSrcSanitizationWhitelist = function(regexp) {
7295             if (isDefined(regexp)) {
7296               $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
7297               return this;
7298             } else {
7299               return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
7300             }
7301           };
7302
7303           /**
7304            * @ngdoc method
7305            * @name  $compileProvider#debugInfoEnabled
7306            *
7307            * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the
7308            * current debugInfoEnabled state
7309            * @returns {*} current value if used as getter or itself (chaining) if used as setter
7310            *
7311            * @kind function
7312            *
7313            * @description
7314            * Call this method to enable/disable various debug runtime information in the compiler such as adding
7315            * binding information and a reference to the current scope on to DOM elements.
7316            * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
7317            * * `ng-binding` CSS class
7318            * * `$binding` data property containing an array of the binding expressions
7319            *
7320            * You may want to disable this in production for a significant performance boost. See
7321            * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
7322            *
7323            * The default value is true.
7324            */
7325           var debugInfoEnabled = true;
7326           this.debugInfoEnabled = function(enabled) {
7327             if (isDefined(enabled)) {
7328               debugInfoEnabled = enabled;
7329               return this;
7330             }
7331             return debugInfoEnabled;
7332           };
7333
7334           this.$get = [
7335                     '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
7336                     '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
7337             function($injector,   $interpolate,   $exceptionHandler,   $templateRequest,   $parse,
7338                      $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {
7339
7340             var Attributes = function(element, attributesToCopy) {
7341               if (attributesToCopy) {
7342                 var keys = Object.keys(attributesToCopy);
7343                 var i, l, key;
7344
7345                 for (i = 0, l = keys.length; i < l; i++) {
7346                   key = keys[i];
7347                   this[key] = attributesToCopy[key];
7348                 }
7349               } else {
7350                 this.$attr = {};
7351               }
7352
7353               this.$$element = element;
7354             };
7355
7356             Attributes.prototype = {
7357               /**
7358                * @ngdoc method
7359                * @name $compile.directive.Attributes#$normalize
7360                * @kind function
7361                *
7362                * @description
7363                * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
7364                * `data-`) to its normalized, camelCase form.
7365                *
7366                * Also there is special case for Moz prefix starting with upper case letter.
7367                *
7368                * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
7369                *
7370                * @param {string} name Name to normalize
7371                */
7372               $normalize: directiveNormalize,
7373
7374
7375               /**
7376                * @ngdoc method
7377                * @name $compile.directive.Attributes#$addClass
7378                * @kind function
7379                *
7380                * @description
7381                * Adds the CSS class value specified by the classVal parameter to the element. If animations
7382                * are enabled then an animation will be triggered for the class addition.
7383                *
7384                * @param {string} classVal The className value that will be added to the element
7385                */
7386               $addClass: function(classVal) {
7387                 if (classVal && classVal.length > 0) {
7388                   $animate.addClass(this.$$element, classVal);
7389                 }
7390               },
7391
7392               /**
7393                * @ngdoc method
7394                * @name $compile.directive.Attributes#$removeClass
7395                * @kind function
7396                *
7397                * @description
7398                * Removes the CSS class value specified by the classVal parameter from the element. If
7399                * animations are enabled then an animation will be triggered for the class removal.
7400                *
7401                * @param {string} classVal The className value that will be removed from the element
7402                */
7403               $removeClass: function(classVal) {
7404                 if (classVal && classVal.length > 0) {
7405                   $animate.removeClass(this.$$element, classVal);
7406                 }
7407               },
7408
7409               /**
7410                * @ngdoc method
7411                * @name $compile.directive.Attributes#$updateClass
7412                * @kind function
7413                *
7414                * @description
7415                * Adds and removes the appropriate CSS class values to the element based on the difference
7416                * between the new and old CSS class values (specified as newClasses and oldClasses).
7417                *
7418                * @param {string} newClasses The current CSS className value
7419                * @param {string} oldClasses The former CSS className value
7420                */
7421               $updateClass: function(newClasses, oldClasses) {
7422                 var toAdd = tokenDifference(newClasses, oldClasses);
7423                 if (toAdd && toAdd.length) {
7424                   $animate.addClass(this.$$element, toAdd);
7425                 }
7426
7427                 var toRemove = tokenDifference(oldClasses, newClasses);
7428                 if (toRemove && toRemove.length) {
7429                   $animate.removeClass(this.$$element, toRemove);
7430                 }
7431               },
7432
7433               /**
7434                * Set a normalized attribute on the element in a way such that all directives
7435                * can share the attribute. This function properly handles boolean attributes.
7436                * @param {string} key Normalized key. (ie ngAttribute)
7437                * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
7438                * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
7439                *     Defaults to true.
7440                * @param {string=} attrName Optional none normalized name. Defaults to key.
7441                */
7442               $set: function(key, value, writeAttr, attrName) {
7443                 // TODO: decide whether or not to throw an error if "class"
7444                 //is set through this function since it may cause $updateClass to
7445                 //become unstable.
7446
7447                 var node = this.$$element[0],
7448                     booleanKey = getBooleanAttrName(node, key),
7449                     aliasedKey = getAliasedAttrName(key),
7450                     observer = key,
7451                     nodeName;
7452
7453                 if (booleanKey) {
7454                   this.$$element.prop(key, value);
7455                   attrName = booleanKey;
7456                 } else if (aliasedKey) {
7457                   this[aliasedKey] = value;
7458                   observer = aliasedKey;
7459                 }
7460
7461                 this[key] = value;
7462
7463                 // translate normalized key to actual key
7464                 if (attrName) {
7465                   this.$attr[key] = attrName;
7466                 } else {
7467                   attrName = this.$attr[key];
7468                   if (!attrName) {
7469                     this.$attr[key] = attrName = snake_case(key, '-');
7470                   }
7471                 }
7472
7473                 nodeName = nodeName_(this.$$element);
7474
7475                 if ((nodeName === 'a' && key === 'href') ||
7476                     (nodeName === 'img' && key === 'src')) {
7477                   // sanitize a[href] and img[src] values
7478                   this[key] = value = $$sanitizeUri(value, key === 'src');
7479                 } else if (nodeName === 'img' && key === 'srcset') {
7480                   // sanitize img[srcset] values
7481                   var result = "";
7482
7483                   // first check if there are spaces because it's not the same pattern
7484                   var trimmedSrcset = trim(value);
7485                   //                (   999x   ,|   999w   ,|   ,|,   )
7486                   var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
7487                   var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
7488
7489                   // split srcset into tuple of uri and descriptor except for the last item
7490                   var rawUris = trimmedSrcset.split(pattern);
7491
7492                   // for each tuples
7493                   var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
7494                   for (var i = 0; i < nbrUrisWith2parts; i++) {
7495                     var innerIdx = i * 2;
7496                     // sanitize the uri
7497                     result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
7498                     // add the descriptor
7499                     result += (" " + trim(rawUris[innerIdx + 1]));
7500                   }
7501
7502                   // split the last item into uri and descriptor
7503                   var lastTuple = trim(rawUris[i * 2]).split(/\s/);
7504
7505                   // sanitize the last uri
7506                   result += $$sanitizeUri(trim(lastTuple[0]), true);
7507
7508                   // and add the last descriptor if any
7509                   if (lastTuple.length === 2) {
7510                     result += (" " + trim(lastTuple[1]));
7511                   }
7512                   this[key] = value = result;
7513                 }
7514
7515                 if (writeAttr !== false) {
7516                   if (value === null || isUndefined(value)) {
7517                     this.$$element.removeAttr(attrName);
7518                   } else {
7519                     this.$$element.attr(attrName, value);
7520                   }
7521                 }
7522
7523                 // fire observers
7524                 var $$observers = this.$$observers;
7525                 $$observers && forEach($$observers[observer], function(fn) {
7526                   try {
7527                     fn(value);
7528                   } catch (e) {
7529                     $exceptionHandler(e);
7530                   }
7531                 });
7532               },
7533
7534
7535               /**
7536                * @ngdoc method
7537                * @name $compile.directive.Attributes#$observe
7538                * @kind function
7539                *
7540                * @description
7541                * Observes an interpolated attribute.
7542                *
7543                * The observer function will be invoked once during the next `$digest` following
7544                * compilation. The observer is then invoked whenever the interpolated value
7545                * changes.
7546                *
7547                * @param {string} key Normalized key. (ie ngAttribute) .
7548                * @param {function(interpolatedValue)} fn Function that will be called whenever
7549                         the interpolated value of the attribute changes.
7550                *        See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
7551                * @returns {function()} Returns a deregistration function for this observer.
7552                */
7553               $observe: function(key, fn) {
7554                 var attrs = this,
7555                     $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
7556                     listeners = ($$observers[key] || ($$observers[key] = []));
7557
7558                 listeners.push(fn);
7559                 $rootScope.$evalAsync(function() {
7560                   if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {
7561                     // no one registered attribute interpolation function, so lets call it manually
7562                     fn(attrs[key]);
7563                   }
7564                 });
7565
7566                 return function() {
7567                   arrayRemove(listeners, fn);
7568                 };
7569               }
7570             };
7571
7572
7573             function safeAddClass($element, className) {
7574               try {
7575                 $element.addClass(className);
7576               } catch (e) {
7577                 // ignore, since it means that we are trying to set class on
7578                 // SVG element, where class name is read-only.
7579               }
7580             }
7581
7582
7583             var startSymbol = $interpolate.startSymbol(),
7584                 endSymbol = $interpolate.endSymbol(),
7585                 denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')
7586                     ? identity
7587                     : function denormalizeTemplate(template) {
7588                       return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
7589                 },
7590                 NG_ATTR_BINDING = /^ngAttr[A-Z]/;
7591             var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;
7592
7593             compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
7594               var bindings = $element.data('$binding') || [];
7595
7596               if (isArray(binding)) {
7597                 bindings = bindings.concat(binding);
7598               } else {
7599                 bindings.push(binding);
7600               }
7601
7602               $element.data('$binding', bindings);
7603             } : noop;
7604
7605             compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {
7606               safeAddClass($element, 'ng-binding');
7607             } : noop;
7608
7609             compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {
7610               var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';
7611               $element.data(dataName, scope);
7612             } : noop;
7613
7614             compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {
7615               safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');
7616             } : noop;
7617
7618             return compile;
7619
7620             //================================
7621
7622             function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
7623                                 previousCompileContext) {
7624               if (!($compileNodes instanceof jqLite)) {
7625                 // jquery always rewraps, whereas we need to preserve the original selector so that we can
7626                 // modify it.
7627                 $compileNodes = jqLite($compileNodes);
7628               }
7629               // We can not compile top level text elements since text nodes can be merged and we will
7630               // not be able to attach scope data to them, so we will wrap them in <span>
7631               forEach($compileNodes, function(node, index) {
7632                 if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
7633                   $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
7634                 }
7635               });
7636               var compositeLinkFn =
7637                       compileNodes($compileNodes, transcludeFn, $compileNodes,
7638                                    maxPriority, ignoreDirective, previousCompileContext);
7639               compile.$$addScopeClass($compileNodes);
7640               var namespace = null;
7641               return function publicLinkFn(scope, cloneConnectFn, options) {
7642                 assertArg(scope, 'scope');
7643
7644                 if (previousCompileContext && previousCompileContext.needsNewScope) {
7645                   // A parent directive did a replace and a directive on this element asked
7646                   // for transclusion, which caused us to lose a layer of element on which
7647                   // we could hold the new transclusion scope, so we will create it manually
7648                   // here.
7649                   scope = scope.$parent.$new();
7650                 }
7651
7652                 options = options || {};
7653                 var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
7654                   transcludeControllers = options.transcludeControllers,
7655                   futureParentElement = options.futureParentElement;
7656
7657                 // When `parentBoundTranscludeFn` is passed, it is a
7658                 // `controllersBoundTransclude` function (it was previously passed
7659                 // as `transclude` to directive.link) so we must unwrap it to get
7660                 // its `boundTranscludeFn`
7661                 if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {
7662                   parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;
7663                 }
7664
7665                 if (!namespace) {
7666                   namespace = detectNamespaceForChildElements(futureParentElement);
7667                 }
7668                 var $linkNode;
7669                 if (namespace !== 'html') {
7670                   // When using a directive with replace:true and templateUrl the $compileNodes
7671                   // (or a child element inside of them)
7672                   // might change, so we need to recreate the namespace adapted compileNodes
7673                   // for call to the link function.
7674                   // Note: This will already clone the nodes...
7675                   $linkNode = jqLite(
7676                     wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
7677                   );
7678                 } else if (cloneConnectFn) {
7679                   // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
7680                   // and sometimes changes the structure of the DOM.
7681                   $linkNode = JQLitePrototype.clone.call($compileNodes);
7682                 } else {
7683                   $linkNode = $compileNodes;
7684                 }
7685
7686                 if (transcludeControllers) {
7687                   for (var controllerName in transcludeControllers) {
7688                     $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);
7689                   }
7690                 }
7691
7692                 compile.$$addScopeInfo($linkNode, scope);
7693
7694                 if (cloneConnectFn) cloneConnectFn($linkNode, scope);
7695                 if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
7696                 return $linkNode;
7697               };
7698             }
7699
7700             function detectNamespaceForChildElements(parentElement) {
7701               // TODO: Make this detect MathML as well...
7702               var node = parentElement && parentElement[0];
7703               if (!node) {
7704                 return 'html';
7705               } else {
7706                 return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
7707               }
7708             }
7709
7710             /**
7711              * Compile function matches each node in nodeList against the directives. Once all directives
7712              * for a particular node are collected their compile functions are executed. The compile
7713              * functions return values - the linking functions - are combined into a composite linking
7714              * function, which is the a linking function for the node.
7715              *
7716              * @param {NodeList} nodeList an array of nodes or NodeList to compile
7717              * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
7718              *        scope argument is auto-generated to the new child of the transcluded parent scope.
7719              * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
7720              *        the rootElement must be set the jqLite collection of the compile root. This is
7721              *        needed so that the jqLite collection items can be replaced with widgets.
7722              * @param {number=} maxPriority Max directive priority.
7723              * @returns {Function} A composite linking function of all of the matched directives or null.
7724              */
7725             function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
7726                                     previousCompileContext) {
7727               var linkFns = [],
7728                   attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;
7729
7730               for (var i = 0; i < nodeList.length; i++) {
7731                 attrs = new Attributes();
7732
7733                 // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
7734                 directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
7735                                                 ignoreDirective);
7736
7737                 nodeLinkFn = (directives.length)
7738                     ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
7739                                               null, [], [], previousCompileContext)
7740                     : null;
7741
7742                 if (nodeLinkFn && nodeLinkFn.scope) {
7743                   compile.$$addScopeClass(attrs.$$element);
7744                 }
7745
7746                 childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
7747                               !(childNodes = nodeList[i].childNodes) ||
7748                               !childNodes.length)
7749                     ? null
7750                     : compileNodes(childNodes,
7751                          nodeLinkFn ? (
7752                           (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
7753                              && nodeLinkFn.transclude) : transcludeFn);
7754
7755                 if (nodeLinkFn || childLinkFn) {
7756                   linkFns.push(i, nodeLinkFn, childLinkFn);
7757                   linkFnFound = true;
7758                   nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
7759                 }
7760
7761                 //use the previous context only for the first element in the virtual group
7762                 previousCompileContext = null;
7763               }
7764
7765               // return a linking function if we have found anything, null otherwise
7766               return linkFnFound ? compositeLinkFn : null;
7767
7768               function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
7769                 var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
7770                 var stableNodeList;
7771
7772
7773                 if (nodeLinkFnFound) {
7774                   // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our
7775                   // offsets don't get screwed up
7776                   var nodeListLength = nodeList.length;
7777                   stableNodeList = new Array(nodeListLength);
7778
7779                   // create a sparse array by only copying the elements which have a linkFn
7780                   for (i = 0; i < linkFns.length; i+=3) {
7781                     idx = linkFns[i];
7782                     stableNodeList[idx] = nodeList[idx];
7783                   }
7784                 } else {
7785                   stableNodeList = nodeList;
7786                 }
7787
7788                 for (i = 0, ii = linkFns.length; i < ii;) {
7789                   node = stableNodeList[linkFns[i++]];
7790                   nodeLinkFn = linkFns[i++];
7791                   childLinkFn = linkFns[i++];
7792
7793                   if (nodeLinkFn) {
7794                     if (nodeLinkFn.scope) {
7795                       childScope = scope.$new();
7796                       compile.$$addScopeInfo(jqLite(node), childScope);
7797                     } else {
7798                       childScope = scope;
7799                     }
7800
7801                     if (nodeLinkFn.transcludeOnThisElement) {
7802                       childBoundTranscludeFn = createBoundTranscludeFn(
7803                           scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
7804
7805                     } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
7806                       childBoundTranscludeFn = parentBoundTranscludeFn;
7807
7808                     } else if (!parentBoundTranscludeFn && transcludeFn) {
7809                       childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
7810
7811                     } else {
7812                       childBoundTranscludeFn = null;
7813                     }
7814
7815                     nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
7816
7817                   } else if (childLinkFn) {
7818                     childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
7819                   }
7820                 }
7821               }
7822             }
7823
7824             function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
7825
7826               var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
7827
7828                 if (!transcludedScope) {
7829                   transcludedScope = scope.$new(false, containingScope);
7830                   transcludedScope.$$transcluded = true;
7831                 }
7832
7833                 return transcludeFn(transcludedScope, cloneFn, {
7834                   parentBoundTranscludeFn: previousBoundTranscludeFn,
7835                   transcludeControllers: controllers,
7836                   futureParentElement: futureParentElement
7837                 });
7838               };
7839
7840               return boundTranscludeFn;
7841             }
7842
7843             /**
7844              * Looks for directives on the given node and adds them to the directive collection which is
7845              * sorted.
7846              *
7847              * @param node Node to search.
7848              * @param directives An array to which the directives are added to. This array is sorted before
7849              *        the function returns.
7850              * @param attrs The shared attrs object which is used to populate the normalized attributes.
7851              * @param {number=} maxPriority Max directive priority.
7852              */
7853             function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
7854               var nodeType = node.nodeType,
7855                   attrsMap = attrs.$attr,
7856                   match,
7857                   className;
7858
7859               switch (nodeType) {
7860                 case NODE_TYPE_ELEMENT: /* Element */
7861                   // use the node name: <directive>
7862                   addDirective(directives,
7863                       directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
7864
7865                   // iterate over the attributes
7866                   for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
7867                            j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
7868                     var attrStartName = false;
7869                     var attrEndName = false;
7870
7871                     attr = nAttrs[j];
7872                     name = attr.name;
7873                     value = trim(attr.value);
7874
7875                     // support ngAttr attribute binding
7876                     ngAttrName = directiveNormalize(name);
7877                     if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
7878                       name = name.replace(PREFIX_REGEXP, '')
7879                         .substr(8).replace(/_(.)/g, function(match, letter) {
7880                           return letter.toUpperCase();
7881                         });
7882                     }
7883
7884                     var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);
7885                     if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {
7886                       attrStartName = name;
7887                       attrEndName = name.substr(0, name.length - 5) + 'end';
7888                       name = name.substr(0, name.length - 6);
7889                     }
7890
7891                     nName = directiveNormalize(name.toLowerCase());
7892                     attrsMap[nName] = name;
7893                     if (isNgAttr || !attrs.hasOwnProperty(nName)) {
7894                         attrs[nName] = value;
7895                         if (getBooleanAttrName(node, nName)) {
7896                           attrs[nName] = true; // presence means true
7897                         }
7898                     }
7899                     addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
7900                     addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
7901                                   attrEndName);
7902                   }
7903
7904                   // use class as directive
7905                   className = node.className;
7906                   if (isObject(className)) {
7907                       // Maybe SVGAnimatedString
7908                       className = className.animVal;
7909                   }
7910                   if (isString(className) && className !== '') {
7911                     while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
7912                       nName = directiveNormalize(match[2]);
7913                       if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
7914                         attrs[nName] = trim(match[3]);
7915                       }
7916                       className = className.substr(match.index + match[0].length);
7917                     }
7918                   }
7919                   break;
7920                 case NODE_TYPE_TEXT: /* Text Node */
7921                   if (msie === 11) {
7922                     // Workaround for #11781
7923                     while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) {
7924                       node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
7925                       node.parentNode.removeChild(node.nextSibling);
7926                     }
7927                   }
7928                   addTextInterpolateDirective(directives, node.nodeValue);
7929                   break;
7930                 case NODE_TYPE_COMMENT: /* Comment */
7931                   try {
7932                     match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
7933                     if (match) {
7934                       nName = directiveNormalize(match[1]);
7935                       if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
7936                         attrs[nName] = trim(match[2]);
7937                       }
7938                     }
7939                   } catch (e) {
7940                     // turns out that under some circumstances IE9 throws errors when one attempts to read
7941                     // comment's node value.
7942                     // Just ignore it and continue. (Can't seem to reproduce in test case.)
7943                   }
7944                   break;
7945               }
7946
7947               directives.sort(byPriority);
7948               return directives;
7949             }
7950
7951             /**
7952              * Given a node with an directive-start it collects all of the siblings until it finds
7953              * directive-end.
7954              * @param node
7955              * @param attrStart
7956              * @param attrEnd
7957              * @returns {*}
7958              */
7959             function groupScan(node, attrStart, attrEnd) {
7960               var nodes = [];
7961               var depth = 0;
7962               if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
7963                 do {
7964                   if (!node) {
7965                     throw $compileMinErr('uterdir',
7966                               "Unterminated attribute, found '{0}' but no matching '{1}' found.",
7967                               attrStart, attrEnd);
7968                   }
7969                   if (node.nodeType == NODE_TYPE_ELEMENT) {
7970                     if (node.hasAttribute(attrStart)) depth++;
7971                     if (node.hasAttribute(attrEnd)) depth--;
7972                   }
7973                   nodes.push(node);
7974                   node = node.nextSibling;
7975                 } while (depth > 0);
7976               } else {
7977                 nodes.push(node);
7978               }
7979
7980               return jqLite(nodes);
7981             }
7982
7983             /**
7984              * Wrapper for linking function which converts normal linking function into a grouped
7985              * linking function.
7986              * @param linkFn
7987              * @param attrStart
7988              * @param attrEnd
7989              * @returns {Function}
7990              */
7991             function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
7992               return function(scope, element, attrs, controllers, transcludeFn) {
7993                 element = groupScan(element[0], attrStart, attrEnd);
7994                 return linkFn(scope, element, attrs, controllers, transcludeFn);
7995               };
7996             }
7997
7998             /**
7999              * Once the directives have been collected, their compile functions are executed. This method
8000              * is responsible for inlining directive templates as well as terminating the application
8001              * of the directives if the terminal directive has been reached.
8002              *
8003              * @param {Array} directives Array of collected directives to execute their compile function.
8004              *        this needs to be pre-sorted by priority order.
8005              * @param {Node} compileNode The raw DOM node to apply the compile functions to
8006              * @param {Object} templateAttrs The shared attribute function
8007              * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
8008              *                                                  scope argument is auto-generated to the new
8009              *                                                  child of the transcluded parent scope.
8010              * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
8011              *                              argument has the root jqLite array so that we can replace nodes
8012              *                              on it.
8013              * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
8014              *                                           compiling the transclusion.
8015              * @param {Array.<Function>} preLinkFns
8016              * @param {Array.<Function>} postLinkFns
8017              * @param {Object} previousCompileContext Context used for previous compilation of the current
8018              *                                        node
8019              * @returns {Function} linkFn
8020              */
8021             function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
8022                                            jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
8023                                            previousCompileContext) {
8024               previousCompileContext = previousCompileContext || {};
8025
8026               var terminalPriority = -Number.MAX_VALUE,
8027                   newScopeDirective = previousCompileContext.newScopeDirective,
8028                   controllerDirectives = previousCompileContext.controllerDirectives,
8029                   newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
8030                   templateDirective = previousCompileContext.templateDirective,
8031                   nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
8032                   hasTranscludeDirective = false,
8033                   hasTemplate = false,
8034                   hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
8035                   $compileNode = templateAttrs.$$element = jqLite(compileNode),
8036                   directive,
8037                   directiveName,
8038                   $template,
8039                   replaceDirective = originalReplaceDirective,
8040                   childTranscludeFn = transcludeFn,
8041                   linkFn,
8042                   directiveValue;
8043
8044               // executes all directives on the current element
8045               for (var i = 0, ii = directives.length; i < ii; i++) {
8046                 directive = directives[i];
8047                 var attrStart = directive.$$start;
8048                 var attrEnd = directive.$$end;
8049
8050                 // collect multiblock sections
8051                 if (attrStart) {
8052                   $compileNode = groupScan(compileNode, attrStart, attrEnd);
8053                 }
8054                 $template = undefined;
8055
8056                 if (terminalPriority > directive.priority) {
8057                   break; // prevent further processing of directives
8058                 }
8059
8060                 if (directiveValue = directive.scope) {
8061
8062                   // skip the check for directives with async templates, we'll check the derived sync
8063                   // directive when the template arrives
8064                   if (!directive.templateUrl) {
8065                     if (isObject(directiveValue)) {
8066                       // This directive is trying to add an isolated scope.
8067                       // Check that there is no scope of any kind already
8068                       assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,
8069                                         directive, $compileNode);
8070                       newIsolateScopeDirective = directive;
8071                     } else {
8072                       // This directive is trying to add a child scope.
8073                       // Check that there is no isolated scope already
8074                       assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
8075                                         $compileNode);
8076                     }
8077                   }
8078
8079                   newScopeDirective = newScopeDirective || directive;
8080                 }
8081
8082                 directiveName = directive.name;
8083
8084                 if (!directive.templateUrl && directive.controller) {
8085                   directiveValue = directive.controller;
8086                   controllerDirectives = controllerDirectives || createMap();
8087                   assertNoDuplicate("'" + directiveName + "' controller",
8088                       controllerDirectives[directiveName], directive, $compileNode);
8089                   controllerDirectives[directiveName] = directive;
8090                 }
8091
8092                 if (directiveValue = directive.transclude) {
8093                   hasTranscludeDirective = true;
8094
8095                   // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
8096                   // This option should only be used by directives that know how to safely handle element transclusion,
8097                   // where the transcluded nodes are added or replaced after linking.
8098                   if (!directive.$$tlb) {
8099                     assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
8100                     nonTlbTranscludeDirective = directive;
8101                   }
8102
8103                   if (directiveValue == 'element') {
8104                     hasElementTranscludeDirective = true;
8105                     terminalPriority = directive.priority;
8106                     $template = $compileNode;
8107                     $compileNode = templateAttrs.$$element =
8108                         jqLite(document.createComment(' ' + directiveName + ': ' +
8109                                                       templateAttrs[directiveName] + ' '));
8110                     compileNode = $compileNode[0];
8111                     replaceWith(jqCollection, sliceArgs($template), compileNode);
8112
8113                     childTranscludeFn = compile($template, transcludeFn, terminalPriority,
8114                                                 replaceDirective && replaceDirective.name, {
8115                                                   // Don't pass in:
8116                                                   // - controllerDirectives - otherwise we'll create duplicates controllers
8117                                                   // - newIsolateScopeDirective or templateDirective - combining templates with
8118                                                   //   element transclusion doesn't make sense.
8119                                                   //
8120                                                   // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
8121                                                   // on the same element more than once.
8122                                                   nonTlbTranscludeDirective: nonTlbTranscludeDirective
8123                                                 });
8124                   } else {
8125                     $template = jqLite(jqLiteClone(compileNode)).contents();
8126                     $compileNode.empty(); // clear contents
8127                     childTranscludeFn = compile($template, transcludeFn, undefined,
8128                         undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
8129                   }
8130                 }
8131
8132                 if (directive.template) {
8133                   hasTemplate = true;
8134                   assertNoDuplicate('template', templateDirective, directive, $compileNode);
8135                   templateDirective = directive;
8136
8137                   directiveValue = (isFunction(directive.template))
8138                       ? directive.template($compileNode, templateAttrs)
8139                       : directive.template;
8140
8141                   directiveValue = denormalizeTemplate(directiveValue);
8142
8143                   if (directive.replace) {
8144                     replaceDirective = directive;
8145                     if (jqLiteIsTextNode(directiveValue)) {
8146                       $template = [];
8147                     } else {
8148                       $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));
8149                     }
8150                     compileNode = $template[0];
8151
8152                     if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
8153                       throw $compileMinErr('tplrt',
8154                           "Template for directive '{0}' must have exactly one root element. {1}",
8155                           directiveName, '');
8156                     }
8157
8158                     replaceWith(jqCollection, $compileNode, compileNode);
8159
8160                     var newTemplateAttrs = {$attr: {}};
8161
8162                     // combine directives from the original node and from the template:
8163                     // - take the array of directives for this element
8164                     // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
8165                     // - collect directives from the template and sort them by priority
8166                     // - combine directives as: processed + template + unprocessed
8167                     var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
8168                     var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
8169
8170                     if (newIsolateScopeDirective || newScopeDirective) {
8171                       // The original directive caused the current element to be replaced but this element
8172                       // also needs to have a new scope, so we need to tell the template directives
8173                       // that they would need to get their scope from further up, if they require transclusion
8174                       markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);
8175                     }
8176                     directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
8177                     mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
8178
8179                     ii = directives.length;
8180                   } else {
8181                     $compileNode.html(directiveValue);
8182                   }
8183                 }
8184
8185                 if (directive.templateUrl) {
8186                   hasTemplate = true;
8187                   assertNoDuplicate('template', templateDirective, directive, $compileNode);
8188                   templateDirective = directive;
8189
8190                   if (directive.replace) {
8191                     replaceDirective = directive;
8192                   }
8193
8194                   nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
8195                       templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
8196                         controllerDirectives: controllerDirectives,
8197                         newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
8198                         newIsolateScopeDirective: newIsolateScopeDirective,
8199                         templateDirective: templateDirective,
8200                         nonTlbTranscludeDirective: nonTlbTranscludeDirective
8201                       });
8202                   ii = directives.length;
8203                 } else if (directive.compile) {
8204                   try {
8205                     linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
8206                     if (isFunction(linkFn)) {
8207                       addLinkFns(null, linkFn, attrStart, attrEnd);
8208                     } else if (linkFn) {
8209                       addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
8210                     }
8211                   } catch (e) {
8212                     $exceptionHandler(e, startingTag($compileNode));
8213                   }
8214                 }
8215
8216                 if (directive.terminal) {
8217                   nodeLinkFn.terminal = true;
8218                   terminalPriority = Math.max(terminalPriority, directive.priority);
8219                 }
8220
8221               }
8222
8223               nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
8224               nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
8225               nodeLinkFn.templateOnThisElement = hasTemplate;
8226               nodeLinkFn.transclude = childTranscludeFn;
8227
8228               previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
8229
8230               // might be normal or delayed nodeLinkFn depending on if templateUrl is present
8231               return nodeLinkFn;
8232
8233               ////////////////////
8234
8235               function addLinkFns(pre, post, attrStart, attrEnd) {
8236                 if (pre) {
8237                   if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
8238                   pre.require = directive.require;
8239                   pre.directiveName = directiveName;
8240                   if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
8241                     pre = cloneAndAnnotateFn(pre, {isolateScope: true});
8242                   }
8243                   preLinkFns.push(pre);
8244                 }
8245                 if (post) {
8246                   if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
8247                   post.require = directive.require;
8248                   post.directiveName = directiveName;
8249                   if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
8250                     post = cloneAndAnnotateFn(post, {isolateScope: true});
8251                   }
8252                   postLinkFns.push(post);
8253                 }
8254               }
8255
8256
8257               function getControllers(directiveName, require, $element, elementControllers) {
8258                 var value;
8259
8260                 if (isString(require)) {
8261                   var match = require.match(REQUIRE_PREFIX_REGEXP);
8262                   var name = require.substring(match[0].length);
8263                   var inheritType = match[1] || match[3];
8264                   var optional = match[2] === '?';
8265
8266                   //If only parents then start at the parent element
8267                   if (inheritType === '^^') {
8268                     $element = $element.parent();
8269                   //Otherwise attempt getting the controller from elementControllers in case
8270                   //the element is transcluded (and has no data) and to avoid .data if possible
8271                   } else {
8272                     value = elementControllers && elementControllers[name];
8273                     value = value && value.instance;
8274                   }
8275
8276                   if (!value) {
8277                     var dataName = '$' + name + 'Controller';
8278                     value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
8279                   }
8280
8281                   if (!value && !optional) {
8282                     throw $compileMinErr('ctreq',
8283                         "Controller '{0}', required by directive '{1}', can't be found!",
8284                         name, directiveName);
8285                   }
8286                 } else if (isArray(require)) {
8287                   value = [];
8288                   for (var i = 0, ii = require.length; i < ii; i++) {
8289                     value[i] = getControllers(directiveName, require[i], $element, elementControllers);
8290                   }
8291                 }
8292
8293                 return value || null;
8294               }
8295
8296               function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) {
8297                 var elementControllers = createMap();
8298                 for (var controllerKey in controllerDirectives) {
8299                   var directive = controllerDirectives[controllerKey];
8300                   var locals = {
8301                     $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
8302                     $element: $element,
8303                     $attrs: attrs,
8304                     $transclude: transcludeFn
8305                   };
8306
8307                   var controller = directive.controller;
8308                   if (controller == '@') {
8309                     controller = attrs[directive.name];
8310                   }
8311
8312                   var controllerInstance = $controller(controller, locals, true, directive.controllerAs);
8313
8314                   // For directives with element transclusion the element is a comment,
8315                   // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
8316                   // clean up (http://bugs.jquery.com/ticket/8335).
8317                   // Instead, we save the controllers for the element in a local hash and attach to .data
8318                   // later, once we have the actual element.
8319                   elementControllers[directive.name] = controllerInstance;
8320                   if (!hasElementTranscludeDirective) {
8321                     $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
8322                   }
8323                 }
8324                 return elementControllers;
8325               }
8326
8327               function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
8328                 var linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
8329                     attrs, removeScopeBindingWatches, removeControllerBindingWatches;
8330
8331                 if (compileNode === linkNode) {
8332                   attrs = templateAttrs;
8333                   $element = templateAttrs.$$element;
8334                 } else {
8335                   $element = jqLite(linkNode);
8336                   attrs = new Attributes($element, templateAttrs);
8337                 }
8338
8339                 controllerScope = scope;
8340                 if (newIsolateScopeDirective) {
8341                   isolateScope = scope.$new(true);
8342                 } else if (newScopeDirective) {
8343                   controllerScope = scope.$parent;
8344                 }
8345
8346                 if (boundTranscludeFn) {
8347                   // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
8348                   // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
8349                   transcludeFn = controllersBoundTransclude;
8350                   transcludeFn.$$boundTransclude = boundTranscludeFn;
8351                 }
8352
8353                 if (controllerDirectives) {
8354                   elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope);
8355                 }
8356
8357                 if (newIsolateScopeDirective) {
8358                   // Initialize isolate scope bindings for new isolate scope directive.
8359                   compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
8360                       templateDirective === newIsolateScopeDirective.$$originalDirective)));
8361                   compile.$$addScopeClass($element, true);
8362                   isolateScope.$$isolateBindings =
8363                       newIsolateScopeDirective.$$isolateBindings;
8364                   removeScopeBindingWatches = initializeDirectiveBindings(scope, attrs, isolateScope,
8365                                                 isolateScope.$$isolateBindings,
8366                                                 newIsolateScopeDirective);
8367                   if (removeScopeBindingWatches) {
8368                     isolateScope.$on('$destroy', removeScopeBindingWatches);
8369                   }
8370                 }
8371
8372                 // Initialize bindToController bindings
8373                 for (var name in elementControllers) {
8374                   var controllerDirective = controllerDirectives[name];
8375                   var controller = elementControllers[name];
8376                   var bindings = controllerDirective.$$bindings.bindToController;
8377
8378                   if (controller.identifier && bindings) {
8379                     removeControllerBindingWatches =
8380                       initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
8381                   }
8382
8383                   var controllerResult = controller();
8384                   if (controllerResult !== controller.instance) {
8385                     // If the controller constructor has a return value, overwrite the instance
8386                     // from setupControllers
8387                     controller.instance = controllerResult;
8388                     $element.data('$' + controllerDirective.name + 'Controller', controllerResult);
8389                     removeControllerBindingWatches && removeControllerBindingWatches();
8390                     removeControllerBindingWatches =
8391                       initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
8392                   }
8393                 }
8394
8395                 // PRELINKING
8396                 for (i = 0, ii = preLinkFns.length; i < ii; i++) {
8397                   linkFn = preLinkFns[i];
8398                   invokeLinkFn(linkFn,
8399                       linkFn.isolateScope ? isolateScope : scope,
8400                       $element,
8401                       attrs,
8402                       linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
8403                       transcludeFn
8404                   );
8405                 }
8406
8407                 // RECURSION
8408                 // We only pass the isolate scope, if the isolate directive has a template,
8409                 // otherwise the child elements do not belong to the isolate directive.
8410                 var scopeToChild = scope;
8411                 if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
8412                   scopeToChild = isolateScope;
8413                 }
8414                 childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
8415
8416                 // POSTLINKING
8417                 for (i = postLinkFns.length - 1; i >= 0; i--) {
8418                   linkFn = postLinkFns[i];
8419                   invokeLinkFn(linkFn,
8420                       linkFn.isolateScope ? isolateScope : scope,
8421                       $element,
8422                       attrs,
8423                       linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
8424                       transcludeFn
8425                   );
8426                 }
8427
8428                 // This is the function that is injected as `$transclude`.
8429                 // Note: all arguments are optional!
8430                 function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
8431                   var transcludeControllers;
8432
8433                   // No scope passed in:
8434                   if (!isScope(scope)) {
8435                     futureParentElement = cloneAttachFn;
8436                     cloneAttachFn = scope;
8437                     scope = undefined;
8438                   }
8439
8440                   if (hasElementTranscludeDirective) {
8441                     transcludeControllers = elementControllers;
8442                   }
8443                   if (!futureParentElement) {
8444                     futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
8445                   }
8446                   return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
8447                 }
8448               }
8449             }
8450
8451             // Depending upon the context in which a directive finds itself it might need to have a new isolated
8452             // or child scope created. For instance:
8453             // * if the directive has been pulled into a template because another directive with a higher priority
8454             // asked for element transclusion
8455             // * if the directive itself asks for transclusion but it is at the root of a template and the original
8456             // element was replaced. See https://github.com/angular/angular.js/issues/12936
8457             function markDirectiveScope(directives, isolateScope, newScope) {
8458               for (var j = 0, jj = directives.length; j < jj; j++) {
8459                 directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});
8460               }
8461             }
8462
8463             /**
8464              * looks up the directive and decorates it with exception handling and proper parameters. We
8465              * call this the boundDirective.
8466              *
8467              * @param {string} name name of the directive to look up.
8468              * @param {string} location The directive must be found in specific format.
8469              *   String containing any of theses characters:
8470              *
8471              *   * `E`: element name
8472              *   * `A': attribute
8473              *   * `C`: class
8474              *   * `M`: comment
8475              * @returns {boolean} true if directive was added.
8476              */
8477             function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
8478                                   endAttrName) {
8479               if (name === ignoreDirective) return null;
8480               var match = null;
8481               if (hasDirectives.hasOwnProperty(name)) {
8482                 for (var directive, directives = $injector.get(name + Suffix),
8483                     i = 0, ii = directives.length; i < ii; i++) {
8484                   try {
8485                     directive = directives[i];
8486                     if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
8487                          directive.restrict.indexOf(location) != -1) {
8488                       if (startAttrName) {
8489                         directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
8490                       }
8491                       tDirectives.push(directive);
8492                       match = directive;
8493                     }
8494                   } catch (e) { $exceptionHandler(e); }
8495                 }
8496               }
8497               return match;
8498             }
8499
8500
8501             /**
8502              * looks up the directive and returns true if it is a multi-element directive,
8503              * and therefore requires DOM nodes between -start and -end markers to be grouped
8504              * together.
8505              *
8506              * @param {string} name name of the directive to look up.
8507              * @returns true if directive was registered as multi-element.
8508              */
8509             function directiveIsMultiElement(name) {
8510               if (hasDirectives.hasOwnProperty(name)) {
8511                 for (var directive, directives = $injector.get(name + Suffix),
8512                     i = 0, ii = directives.length; i < ii; i++) {
8513                   directive = directives[i];
8514                   if (directive.multiElement) {
8515                     return true;
8516                   }
8517                 }
8518               }
8519               return false;
8520             }
8521
8522             /**
8523              * When the element is replaced with HTML template then the new attributes
8524              * on the template need to be merged with the existing attributes in the DOM.
8525              * The desired effect is to have both of the attributes present.
8526              *
8527              * @param {object} dst destination attributes (original DOM)
8528              * @param {object} src source attributes (from the directive template)
8529              */
8530             function mergeTemplateAttributes(dst, src) {
8531               var srcAttr = src.$attr,
8532                   dstAttr = dst.$attr,
8533                   $element = dst.$$element;
8534
8535               // reapply the old attributes to the new element
8536               forEach(dst, function(value, key) {
8537                 if (key.charAt(0) != '$') {
8538                   if (src[key] && src[key] !== value) {
8539                     value += (key === 'style' ? ';' : ' ') + src[key];
8540                   }
8541                   dst.$set(key, value, true, srcAttr[key]);
8542                 }
8543               });
8544
8545               // copy the new attributes on the old attrs object
8546               forEach(src, function(value, key) {
8547                 if (key == 'class') {
8548                   safeAddClass($element, value);
8549                   dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
8550                 } else if (key == 'style') {
8551                   $element.attr('style', $element.attr('style') + ';' + value);
8552                   dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
8553                   // `dst` will never contain hasOwnProperty as DOM parser won't let it.
8554                   // You will get an "InvalidCharacterError: DOM Exception 5" error if you
8555                   // have an attribute like "has-own-property" or "data-has-own-property", etc.
8556                 } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
8557                   dst[key] = value;
8558                   dstAttr[key] = srcAttr[key];
8559                 }
8560               });
8561             }
8562
8563
8564             function compileTemplateUrl(directives, $compileNode, tAttrs,
8565                 $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
8566               var linkQueue = [],
8567                   afterTemplateNodeLinkFn,
8568                   afterTemplateChildLinkFn,
8569                   beforeTemplateCompileNode = $compileNode[0],
8570                   origAsyncDirective = directives.shift(),
8571                   derivedSyncDirective = inherit(origAsyncDirective, {
8572                     templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
8573                   }),
8574                   templateUrl = (isFunction(origAsyncDirective.templateUrl))
8575                       ? origAsyncDirective.templateUrl($compileNode, tAttrs)
8576                       : origAsyncDirective.templateUrl,
8577                   templateNamespace = origAsyncDirective.templateNamespace;
8578
8579               $compileNode.empty();
8580
8581               $templateRequest(templateUrl)
8582                 .then(function(content) {
8583                   var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
8584
8585                   content = denormalizeTemplate(content);
8586
8587                   if (origAsyncDirective.replace) {
8588                     if (jqLiteIsTextNode(content)) {
8589                       $template = [];
8590                     } else {
8591                       $template = removeComments(wrapTemplate(templateNamespace, trim(content)));
8592                     }
8593                     compileNode = $template[0];
8594
8595                     if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
8596                       throw $compileMinErr('tplrt',
8597                           "Template for directive '{0}' must have exactly one root element. {1}",
8598                           origAsyncDirective.name, templateUrl);
8599                     }
8600
8601                     tempTemplateAttrs = {$attr: {}};
8602                     replaceWith($rootElement, $compileNode, compileNode);
8603                     var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
8604
8605                     if (isObject(origAsyncDirective.scope)) {
8606                       // the original directive that caused the template to be loaded async required
8607                       // an isolate scope
8608                       markDirectiveScope(templateDirectives, true);
8609                     }
8610                     directives = templateDirectives.concat(directives);
8611                     mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
8612                   } else {
8613                     compileNode = beforeTemplateCompileNode;
8614                     $compileNode.html(content);
8615                   }
8616
8617                   directives.unshift(derivedSyncDirective);
8618
8619                   afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
8620                       childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
8621                       previousCompileContext);
8622                   forEach($rootElement, function(node, i) {
8623                     if (node == compileNode) {
8624                       $rootElement[i] = $compileNode[0];
8625                     }
8626                   });
8627                   afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
8628
8629                   while (linkQueue.length) {
8630                     var scope = linkQueue.shift(),
8631                         beforeTemplateLinkNode = linkQueue.shift(),
8632                         linkRootElement = linkQueue.shift(),
8633                         boundTranscludeFn = linkQueue.shift(),
8634                         linkNode = $compileNode[0];
8635
8636                     if (scope.$$destroyed) continue;
8637
8638                     if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
8639                       var oldClasses = beforeTemplateLinkNode.className;
8640
8641                       if (!(previousCompileContext.hasElementTranscludeDirective &&
8642                           origAsyncDirective.replace)) {
8643                         // it was cloned therefore we have to clone as well.
8644                         linkNode = jqLiteClone(compileNode);
8645                       }
8646                       replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
8647
8648                       // Copy in CSS classes from original node
8649                       safeAddClass(jqLite(linkNode), oldClasses);
8650                     }
8651                     if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
8652                       childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
8653                     } else {
8654                       childBoundTranscludeFn = boundTranscludeFn;
8655                     }
8656                     afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
8657                       childBoundTranscludeFn);
8658                   }
8659                   linkQueue = null;
8660                 });
8661
8662               return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
8663                 var childBoundTranscludeFn = boundTranscludeFn;
8664                 if (scope.$$destroyed) return;
8665                 if (linkQueue) {
8666                   linkQueue.push(scope,
8667                                  node,
8668                                  rootElement,
8669                                  childBoundTranscludeFn);
8670                 } else {
8671                   if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
8672                     childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
8673                   }
8674                   afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
8675                 }
8676               };
8677             }
8678
8679
8680             /**
8681              * Sorting function for bound directives.
8682              */
8683             function byPriority(a, b) {
8684               var diff = b.priority - a.priority;
8685               if (diff !== 0) return diff;
8686               if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
8687               return a.index - b.index;
8688             }
8689
8690             function assertNoDuplicate(what, previousDirective, directive, element) {
8691
8692               function wrapModuleNameIfDefined(moduleName) {
8693                 return moduleName ?
8694                   (' (module: ' + moduleName + ')') :
8695                   '';
8696               }
8697
8698               if (previousDirective) {
8699                 throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',
8700                     previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),
8701                     directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));
8702               }
8703             }
8704
8705
8706             function addTextInterpolateDirective(directives, text) {
8707               var interpolateFn = $interpolate(text, true);
8708               if (interpolateFn) {
8709                 directives.push({
8710                   priority: 0,
8711                   compile: function textInterpolateCompileFn(templateNode) {
8712                     var templateNodeParent = templateNode.parent(),
8713                         hasCompileParent = !!templateNodeParent.length;
8714
8715                     // When transcluding a template that has bindings in the root
8716                     // we don't have a parent and thus need to add the class during linking fn.
8717                     if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);
8718
8719                     return function textInterpolateLinkFn(scope, node) {
8720                       var parent = node.parent();
8721                       if (!hasCompileParent) compile.$$addBindingClass(parent);
8722                       compile.$$addBindingInfo(parent, interpolateFn.expressions);
8723                       scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
8724                         node[0].nodeValue = value;
8725                       });
8726                     };
8727                   }
8728                 });
8729               }
8730             }
8731
8732
8733             function wrapTemplate(type, template) {
8734               type = lowercase(type || 'html');
8735               switch (type) {
8736               case 'svg':
8737               case 'math':
8738                 var wrapper = document.createElement('div');
8739                 wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
8740                 return wrapper.childNodes[0].childNodes;
8741               default:
8742                 return template;
8743               }
8744             }
8745
8746
8747             function getTrustedContext(node, attrNormalizedName) {
8748               if (attrNormalizedName == "srcdoc") {
8749                 return $sce.HTML;
8750               }
8751               var tag = nodeName_(node);
8752               // maction[xlink:href] can source SVG.  It's not limited to <maction>.
8753               if (attrNormalizedName == "xlinkHref" ||
8754                   (tag == "form" && attrNormalizedName == "action") ||
8755                   (tag != "img" && (attrNormalizedName == "src" ||
8756                                     attrNormalizedName == "ngSrc"))) {
8757                 return $sce.RESOURCE_URL;
8758               }
8759             }
8760
8761
8762             function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
8763               var trustedContext = getTrustedContext(node, name);
8764               allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
8765
8766               var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
8767
8768               // no interpolation found -> ignore
8769               if (!interpolateFn) return;
8770
8771
8772               if (name === "multiple" && nodeName_(node) === "select") {
8773                 throw $compileMinErr("selmulti",
8774                     "Binding to the 'multiple' attribute is not supported. Element: {0}",
8775                     startingTag(node));
8776               }
8777
8778               directives.push({
8779                 priority: 100,
8780                 compile: function() {
8781                     return {
8782                       pre: function attrInterpolatePreLinkFn(scope, element, attr) {
8783                         var $$observers = (attr.$$observers || (attr.$$observers = createMap()));
8784
8785                         if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
8786                           throw $compileMinErr('nodomevents',
8787                               "Interpolations for HTML DOM event attributes are disallowed.  Please use the " +
8788                                   "ng- versions (such as ng-click instead of onclick) instead.");
8789                         }
8790
8791                         // If the attribute has changed since last $interpolate()ed
8792                         var newValue = attr[name];
8793                         if (newValue !== value) {
8794                           // we need to interpolate again since the attribute value has been updated
8795                           // (e.g. by another directive's compile function)
8796                           // ensure unset/empty values make interpolateFn falsy
8797                           interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
8798                           value = newValue;
8799                         }
8800
8801                         // if attribute was updated so that there is no interpolation going on we don't want to
8802                         // register any observers
8803                         if (!interpolateFn) return;
8804
8805                         // initialize attr object so that it's ready in case we need the value for isolate
8806                         // scope initialization, otherwise the value would not be available from isolate
8807                         // directive's linking fn during linking phase
8808                         attr[name] = interpolateFn(scope);
8809
8810                         ($$observers[name] || ($$observers[name] = [])).$$inter = true;
8811                         (attr.$$observers && attr.$$observers[name].$$scope || scope).
8812                           $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
8813                             //special case for class attribute addition + removal
8814                             //so that class changes can tap into the animation
8815                             //hooks provided by the $animate service. Be sure to
8816                             //skip animations when the first digest occurs (when
8817                             //both the new and the old values are the same) since
8818                             //the CSS classes are the non-interpolated values
8819                             if (name === 'class' && newValue != oldValue) {
8820                               attr.$updateClass(newValue, oldValue);
8821                             } else {
8822                               attr.$set(name, newValue);
8823                             }
8824                           });
8825                       }
8826                     };
8827                   }
8828               });
8829             }
8830
8831
8832             /**
8833              * This is a special jqLite.replaceWith, which can replace items which
8834              * have no parents, provided that the containing jqLite collection is provided.
8835              *
8836              * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
8837              *                               in the root of the tree.
8838              * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
8839              *                                  the shell, but replace its DOM node reference.
8840              * @param {Node} newNode The new DOM node.
8841              */
8842             function replaceWith($rootElement, elementsToRemove, newNode) {
8843               var firstElementToRemove = elementsToRemove[0],
8844                   removeCount = elementsToRemove.length,
8845                   parent = firstElementToRemove.parentNode,
8846                   i, ii;
8847
8848               if ($rootElement) {
8849                 for (i = 0, ii = $rootElement.length; i < ii; i++) {
8850                   if ($rootElement[i] == firstElementToRemove) {
8851                     $rootElement[i++] = newNode;
8852                     for (var j = i, j2 = j + removeCount - 1,
8853                              jj = $rootElement.length;
8854                          j < jj; j++, j2++) {
8855                       if (j2 < jj) {
8856                         $rootElement[j] = $rootElement[j2];
8857                       } else {
8858                         delete $rootElement[j];
8859                       }
8860                     }
8861                     $rootElement.length -= removeCount - 1;
8862
8863                     // If the replaced element is also the jQuery .context then replace it
8864                     // .context is a deprecated jQuery api, so we should set it only when jQuery set it
8865                     // http://api.jquery.com/context/
8866                     if ($rootElement.context === firstElementToRemove) {
8867                       $rootElement.context = newNode;
8868                     }
8869                     break;
8870                   }
8871                 }
8872               }
8873
8874               if (parent) {
8875                 parent.replaceChild(newNode, firstElementToRemove);
8876               }
8877
8878               // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
8879               var fragment = document.createDocumentFragment();
8880               fragment.appendChild(firstElementToRemove);
8881
8882               if (jqLite.hasData(firstElementToRemove)) {
8883                 // Copy over user data (that includes Angular's $scope etc.). Don't copy private
8884                 // data here because there's no public interface in jQuery to do that and copying over
8885                 // event listeners (which is the main use of private data) wouldn't work anyway.
8886                 jqLite.data(newNode, jqLite.data(firstElementToRemove));
8887
8888                 // Remove data of the replaced element. We cannot just call .remove()
8889                 // on the element it since that would deallocate scope that is needed
8890                 // for the new node. Instead, remove the data "manually".
8891                 if (!jQuery) {
8892                   delete jqLite.cache[firstElementToRemove[jqLite.expando]];
8893                 } else {
8894                   // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
8895                   // the replaced element. The cleanData version monkey-patched by Angular would cause
8896                   // the scope to be trashed and we do need the very same scope to work with the new
8897                   // element. However, we cannot just cache the non-patched version and use it here as
8898                   // that would break if another library patches the method after Angular does (one
8899                   // example is jQuery UI). Instead, set a flag indicating scope destroying should be
8900                   // skipped this one time.
8901                   skipDestroyOnNextJQueryCleanData = true;
8902                   jQuery.cleanData([firstElementToRemove]);
8903                 }
8904               }
8905
8906               for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
8907                 var element = elementsToRemove[k];
8908                 jqLite(element).remove(); // must do this way to clean up expando
8909                 fragment.appendChild(element);
8910                 delete elementsToRemove[k];
8911               }
8912
8913               elementsToRemove[0] = newNode;
8914               elementsToRemove.length = 1;
8915             }
8916
8917
8918             function cloneAndAnnotateFn(fn, annotation) {
8919               return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
8920             }
8921
8922
8923             function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
8924               try {
8925                 linkFn(scope, $element, attrs, controllers, transcludeFn);
8926               } catch (e) {
8927                 $exceptionHandler(e, startingTag($element));
8928               }
8929             }
8930
8931
8932             // Set up $watches for isolate scope and controller bindings. This process
8933             // only occurs for isolate scopes and new scopes with controllerAs.
8934             function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {
8935               var removeWatchCollection = [];
8936               forEach(bindings, function(definition, scopeName) {
8937                 var attrName = definition.attrName,
8938                 optional = definition.optional,
8939                 mode = definition.mode, // @, =, or &
8940                 lastValue,
8941                 parentGet, parentSet, compare;
8942
8943                 switch (mode) {
8944
8945                   case '@':
8946                     if (!optional && !hasOwnProperty.call(attrs, attrName)) {
8947                       destination[scopeName] = attrs[attrName] = void 0;
8948                     }
8949                     attrs.$observe(attrName, function(value) {
8950                       if (isString(value)) {
8951                         destination[scopeName] = value;
8952                       }
8953                     });
8954                     attrs.$$observers[attrName].$$scope = scope;
8955                     if (isString(attrs[attrName])) {
8956                       // If the attribute has been provided then we trigger an interpolation to ensure
8957                       // the value is there for use in the link fn
8958                       destination[scopeName] = $interpolate(attrs[attrName])(scope);
8959                     }
8960                     break;
8961
8962                   case '=':
8963                     if (!hasOwnProperty.call(attrs, attrName)) {
8964                       if (optional) break;
8965                       attrs[attrName] = void 0;
8966                     }
8967                     if (optional && !attrs[attrName]) break;
8968
8969                     parentGet = $parse(attrs[attrName]);
8970                     if (parentGet.literal) {
8971                       compare = equals;
8972                     } else {
8973                       compare = function(a, b) { return a === b || (a !== a && b !== b); };
8974                     }
8975                     parentSet = parentGet.assign || function() {
8976                       // reset the change, or we will throw this exception on every $digest
8977                       lastValue = destination[scopeName] = parentGet(scope);
8978                       throw $compileMinErr('nonassign',
8979                           "Expression '{0}' used with directive '{1}' is non-assignable!",
8980                           attrs[attrName], directive.name);
8981                     };
8982                     lastValue = destination[scopeName] = parentGet(scope);
8983                     var parentValueWatch = function parentValueWatch(parentValue) {
8984                       if (!compare(parentValue, destination[scopeName])) {
8985                         // we are out of sync and need to copy
8986                         if (!compare(parentValue, lastValue)) {
8987                           // parent changed and it has precedence
8988                           destination[scopeName] = parentValue;
8989                         } else {
8990                           // if the parent can be assigned then do so
8991                           parentSet(scope, parentValue = destination[scopeName]);
8992                         }
8993                       }
8994                       return lastValue = parentValue;
8995                     };
8996                     parentValueWatch.$stateful = true;
8997                     var removeWatch;
8998                     if (definition.collection) {
8999                       removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
9000                     } else {
9001                       removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
9002                     }
9003                     removeWatchCollection.push(removeWatch);
9004                     break;
9005
9006                   case '&':
9007                     // Don't assign Object.prototype method to scope
9008                     parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
9009
9010                     // Don't assign noop to destination if expression is not valid
9011                     if (parentGet === noop && optional) break;
9012
9013                     destination[scopeName] = function(locals) {
9014                       return parentGet(scope, locals);
9015                     };
9016                     break;
9017                 }
9018               });
9019
9020               return removeWatchCollection.length && function removeWatches() {
9021                 for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
9022                   removeWatchCollection[i]();
9023                 }
9024               };
9025             }
9026           }];
9027         }
9028
9029         var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
9030         /**
9031          * Converts all accepted directives format into proper directive name.
9032          * @param name Name to normalize
9033          */
9034         function directiveNormalize(name) {
9035           return camelCase(name.replace(PREFIX_REGEXP, ''));
9036         }
9037
9038         /**
9039          * @ngdoc type
9040          * @name $compile.directive.Attributes
9041          *
9042          * @description
9043          * A shared object between directive compile / linking functions which contains normalized DOM
9044          * element attributes. The values reflect current binding state `{{ }}`. The normalization is
9045          * needed since all of these are treated as equivalent in Angular:
9046          *
9047          * ```
9048          *    <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
9049          * ```
9050          */
9051
9052         /**
9053          * @ngdoc property
9054          * @name $compile.directive.Attributes#$attr
9055          *
9056          * @description
9057          * A map of DOM element attribute names to the normalized name. This is
9058          * needed to do reverse lookup from normalized name back to actual name.
9059          */
9060
9061
9062         /**
9063          * @ngdoc method
9064          * @name $compile.directive.Attributes#$set
9065          * @kind function
9066          *
9067          * @description
9068          * Set DOM element attribute value.
9069          *
9070          *
9071          * @param {string} name Normalized element attribute name of the property to modify. The name is
9072          *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
9073          *          property to the original name.
9074          * @param {string} value Value to set the attribute to. The value can be an interpolated string.
9075          */
9076
9077
9078
9079         /**
9080          * Closure compiler type information
9081          */
9082
9083         function nodesetLinkingFn(
9084           /* angular.Scope */ scope,
9085           /* NodeList */ nodeList,
9086           /* Element */ rootElement,
9087           /* function(Function) */ boundTranscludeFn
9088         ) {}
9089
9090         function directiveLinkingFn(
9091           /* nodesetLinkingFn */ nodesetLinkingFn,
9092           /* angular.Scope */ scope,
9093           /* Node */ node,
9094           /* Element */ rootElement,
9095           /* function(Function) */ boundTranscludeFn
9096         ) {}
9097
9098         function tokenDifference(str1, str2) {
9099           var values = '',
9100               tokens1 = str1.split(/\s+/),
9101               tokens2 = str2.split(/\s+/);
9102
9103           outer:
9104           for (var i = 0; i < tokens1.length; i++) {
9105             var token = tokens1[i];
9106             for (var j = 0; j < tokens2.length; j++) {
9107               if (token == tokens2[j]) continue outer;
9108             }
9109             values += (values.length > 0 ? ' ' : '') + token;
9110           }
9111           return values;
9112         }
9113
9114         function removeComments(jqNodes) {
9115           jqNodes = jqLite(jqNodes);
9116           var i = jqNodes.length;
9117
9118           if (i <= 1) {
9119             return jqNodes;
9120           }
9121
9122           while (i--) {
9123             var node = jqNodes[i];
9124             if (node.nodeType === NODE_TYPE_COMMENT) {
9125               splice.call(jqNodes, i, 1);
9126             }
9127           }
9128           return jqNodes;
9129         }
9130
9131         var $controllerMinErr = minErr('$controller');
9132
9133
9134         var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
9135         function identifierForController(controller, ident) {
9136           if (ident && isString(ident)) return ident;
9137           if (isString(controller)) {
9138             var match = CNTRL_REG.exec(controller);
9139             if (match) return match[3];
9140           }
9141         }
9142
9143
9144         /**
9145          * @ngdoc provider
9146          * @name $controllerProvider
9147          * @description
9148          * The {@link ng.$controller $controller service} is used by Angular to create new
9149          * controllers.
9150          *
9151          * This provider allows controller registration via the
9152          * {@link ng.$controllerProvider#register register} method.
9153          */
9154         function $ControllerProvider() {
9155           var controllers = {},
9156               globals = false;
9157
9158           /**
9159            * @ngdoc method
9160            * @name $controllerProvider#register
9161            * @param {string|Object} name Controller name, or an object map of controllers where the keys are
9162            *    the names and the values are the constructors.
9163            * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
9164            *    annotations in the array notation).
9165            */
9166           this.register = function(name, constructor) {
9167             assertNotHasOwnProperty(name, 'controller');
9168             if (isObject(name)) {
9169               extend(controllers, name);
9170             } else {
9171               controllers[name] = constructor;
9172             }
9173           };
9174
9175           /**
9176            * @ngdoc method
9177            * @name $controllerProvider#allowGlobals
9178            * @description If called, allows `$controller` to find controller constructors on `window`
9179            */
9180           this.allowGlobals = function() {
9181             globals = true;
9182           };
9183
9184
9185           this.$get = ['$injector', '$window', function($injector, $window) {
9186
9187             /**
9188              * @ngdoc service
9189              * @name $controller
9190              * @requires $injector
9191              *
9192              * @param {Function|string} constructor If called with a function then it's considered to be the
9193              *    controller constructor function. Otherwise it's considered to be a string which is used
9194              *    to retrieve the controller constructor using the following steps:
9195              *
9196              *    * check if a controller with given name is registered via `$controllerProvider`
9197              *    * check if evaluating the string on the current scope returns a constructor
9198              *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
9199              *      `window` object (not recommended)
9200              *
9201              *    The string can use the `controller as property` syntax, where the controller instance is published
9202              *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
9203              *    to work correctly.
9204              *
9205              * @param {Object} locals Injection locals for Controller.
9206              * @return {Object} Instance of given controller.
9207              *
9208              * @description
9209              * `$controller` service is responsible for instantiating controllers.
9210              *
9211              * It's just a simple call to {@link auto.$injector $injector}, but extracted into
9212              * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
9213              */
9214             return function(expression, locals, later, ident) {
9215               // PRIVATE API:
9216               //   param `later` --- indicates that the controller's constructor is invoked at a later time.
9217               //                     If true, $controller will allocate the object with the correct
9218               //                     prototype chain, but will not invoke the controller until a returned
9219               //                     callback is invoked.
9220               //   param `ident` --- An optional label which overrides the label parsed from the controller
9221               //                     expression, if any.
9222               var instance, match, constructor, identifier;
9223               later = later === true;
9224               if (ident && isString(ident)) {
9225                 identifier = ident;
9226               }
9227
9228               if (isString(expression)) {
9229                 match = expression.match(CNTRL_REG);
9230                 if (!match) {
9231                   throw $controllerMinErr('ctrlfmt',
9232                     "Badly formed controller string '{0}'. " +
9233                     "Must match `__name__ as __id__` or `__name__`.", expression);
9234                 }
9235                 constructor = match[1],
9236                 identifier = identifier || match[3];
9237                 expression = controllers.hasOwnProperty(constructor)
9238                     ? controllers[constructor]
9239                     : getter(locals.$scope, constructor, true) ||
9240                         (globals ? getter($window, constructor, true) : undefined);
9241
9242                 assertArgFn(expression, constructor, true);
9243               }
9244
9245               if (later) {
9246                 // Instantiate controller later:
9247                 // This machinery is used to create an instance of the object before calling the
9248                 // controller's constructor itself.
9249                 //
9250                 // This allows properties to be added to the controller before the constructor is
9251                 // invoked. Primarily, this is used for isolate scope bindings in $compile.
9252                 //
9253                 // This feature is not intended for use by applications, and is thus not documented
9254                 // publicly.
9255                 // Object creation: http://jsperf.com/create-constructor/2
9256                 var controllerPrototype = (isArray(expression) ?
9257                   expression[expression.length - 1] : expression).prototype;
9258                 instance = Object.create(controllerPrototype || null);
9259
9260                 if (identifier) {
9261                   addIdentifier(locals, identifier, instance, constructor || expression.name);
9262                 }
9263
9264                 var instantiate;
9265                 return instantiate = extend(function() {
9266                   var result = $injector.invoke(expression, instance, locals, constructor);
9267                   if (result !== instance && (isObject(result) || isFunction(result))) {
9268                     instance = result;
9269                     if (identifier) {
9270                       // If result changed, re-assign controllerAs value to scope.
9271                       addIdentifier(locals, identifier, instance, constructor || expression.name);
9272                     }
9273                   }
9274                   return instance;
9275                 }, {
9276                   instance: instance,
9277                   identifier: identifier
9278                 });
9279               }
9280
9281               instance = $injector.instantiate(expression, locals, constructor);
9282
9283               if (identifier) {
9284                 addIdentifier(locals, identifier, instance, constructor || expression.name);
9285               }
9286
9287               return instance;
9288             };
9289
9290             function addIdentifier(locals, identifier, instance, name) {
9291               if (!(locals && isObject(locals.$scope))) {
9292                 throw minErr('$controller')('noscp',
9293                   "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
9294                   name, identifier);
9295               }
9296
9297               locals.$scope[identifier] = instance;
9298             }
9299           }];
9300         }
9301
9302         /**
9303          * @ngdoc service
9304          * @name $document
9305          * @requires $window
9306          *
9307          * @description
9308          * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
9309          *
9310          * @example
9311            <example module="documentExample">
9312              <file name="index.html">
9313                <div ng-controller="ExampleController">
9314                  <p>$document title: <b ng-bind="title"></b></p>
9315                  <p>window.document title: <b ng-bind="windowTitle"></b></p>
9316                </div>
9317              </file>
9318              <file name="script.js">
9319                angular.module('documentExample', [])
9320                  .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
9321                    $scope.title = $document[0].title;
9322                    $scope.windowTitle = angular.element(window.document)[0].title;
9323                  }]);
9324              </file>
9325            </example>
9326          */
9327         function $DocumentProvider() {
9328           this.$get = ['$window', function(window) {
9329             return jqLite(window.document);
9330           }];
9331         }
9332
9333         /**
9334          * @ngdoc service
9335          * @name $exceptionHandler
9336          * @requires ng.$log
9337          *
9338          * @description
9339          * Any uncaught exception in angular expressions is delegated to this service.
9340          * The default implementation simply delegates to `$log.error` which logs it into
9341          * the browser console.
9342          *
9343          * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
9344          * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
9345          *
9346          * ## Example:
9347          *
9348          * ```js
9349          *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
9350          *     return function(exception, cause) {
9351          *       exception.message += ' (caused by "' + cause + '")';
9352          *       throw exception;
9353          *     };
9354          *   });
9355          * ```
9356          *
9357          * This example will override the normal action of `$exceptionHandler`, to make angular
9358          * exceptions fail hard when they happen, instead of just logging to the console.
9359          *
9360          * <hr />
9361          * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`
9362          * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}
9363          * (unless executed during a digest).
9364          *
9365          * If you wish, you can manually delegate exceptions, e.g.
9366          * `try { ... } catch(e) { $exceptionHandler(e); }`
9367          *
9368          * @param {Error} exception Exception associated with the error.
9369          * @param {string=} cause optional information about the context in which
9370          *       the error was thrown.
9371          *
9372          */
9373         function $ExceptionHandlerProvider() {
9374           this.$get = ['$log', function($log) {
9375             return function(exception, cause) {
9376               $log.error.apply($log, arguments);
9377             };
9378           }];
9379         }
9380
9381         var $$ForceReflowProvider = function() {
9382           this.$get = ['$document', function($document) {
9383             return function(domNode) {
9384               //the line below will force the browser to perform a repaint so
9385               //that all the animated elements within the animation frame will
9386               //be properly updated and drawn on screen. This is required to
9387               //ensure that the preparation animation is properly flushed so that
9388               //the active state picks up from there. DO NOT REMOVE THIS LINE.
9389               //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH
9390               //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND
9391               //WILL TAKE YEARS AWAY FROM YOUR LIFE.
9392               if (domNode) {
9393                 if (!domNode.nodeType && domNode instanceof jqLite) {
9394                   domNode = domNode[0];
9395                 }
9396               } else {
9397                 domNode = $document[0].body;
9398               }
9399               return domNode.offsetWidth + 1;
9400             };
9401           }];
9402         };
9403
9404         var APPLICATION_JSON = 'application/json';
9405         var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
9406         var JSON_START = /^\[|^\{(?!\{)/;
9407         var JSON_ENDS = {
9408           '[': /]$/,
9409           '{': /}$/
9410         };
9411         var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
9412         var $httpMinErr = minErr('$http');
9413         var $httpMinErrLegacyFn = function(method) {
9414           return function() {
9415             throw $httpMinErr('legacy', 'The method `{0}` on the promise returned from `$http` has been disabled.', method);
9416           };
9417         };
9418
9419         function serializeValue(v) {
9420           if (isObject(v)) {
9421             return isDate(v) ? v.toISOString() : toJson(v);
9422           }
9423           return v;
9424         }
9425
9426
9427         function $HttpParamSerializerProvider() {
9428           /**
9429            * @ngdoc service
9430            * @name $httpParamSerializer
9431            * @description
9432            *
9433            * Default {@link $http `$http`} params serializer that converts objects to strings
9434            * according to the following rules:
9435            *
9436            * * `{'foo': 'bar'}` results in `foo=bar`
9437            * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)
9438            * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)
9439            * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
9440            *
9441            * Note that serializer will sort the request parameters alphabetically.
9442            * */
9443
9444           this.$get = function() {
9445             return function ngParamSerializer(params) {
9446               if (!params) return '';
9447               var parts = [];
9448               forEachSorted(params, function(value, key) {
9449                 if (value === null || isUndefined(value)) return;
9450                 if (isArray(value)) {
9451                   forEach(value, function(v, k) {
9452                     parts.push(encodeUriQuery(key)  + '=' + encodeUriQuery(serializeValue(v)));
9453                   });
9454                 } else {
9455                   parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));
9456                 }
9457               });
9458
9459               return parts.join('&');
9460             };
9461           };
9462         }
9463
9464         function $HttpParamSerializerJQLikeProvider() {
9465           /**
9466            * @ngdoc service
9467            * @name $httpParamSerializerJQLike
9468            * @description
9469            *
9470            * Alternative {@link $http `$http`} params serializer that follows
9471            * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
9472            * The serializer will also sort the params alphabetically.
9473            *
9474            * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:
9475            *
9476            * ```js
9477            * $http({
9478            *   url: myUrl,
9479            *   method: 'GET',
9480            *   params: myParams,
9481            *   paramSerializer: '$httpParamSerializerJQLike'
9482            * });
9483            * ```
9484            *
9485            * It is also possible to set it as the default `paramSerializer` in the
9486            * {@link $httpProvider#defaults `$httpProvider`}.
9487            *
9488            * Additionally, you can inject the serializer and use it explicitly, for example to serialize
9489            * form data for submission:
9490            *
9491            * ```js
9492            * .controller(function($http, $httpParamSerializerJQLike) {
9493            *   //...
9494            *
9495            *   $http({
9496            *     url: myUrl,
9497            *     method: 'POST',
9498            *     data: $httpParamSerializerJQLike(myData),
9499            *     headers: {
9500            *       'Content-Type': 'application/x-www-form-urlencoded'
9501            *     }
9502            *   });
9503            *
9504            * });
9505            * ```
9506            *
9507            * */
9508           this.$get = function() {
9509             return function jQueryLikeParamSerializer(params) {
9510               if (!params) return '';
9511               var parts = [];
9512               serialize(params, '', true);
9513               return parts.join('&');
9514
9515               function serialize(toSerialize, prefix, topLevel) {
9516                 if (toSerialize === null || isUndefined(toSerialize)) return;
9517                 if (isArray(toSerialize)) {
9518                   forEach(toSerialize, function(value, index) {
9519                     serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');
9520                   });
9521                 } else if (isObject(toSerialize) && !isDate(toSerialize)) {
9522                   forEachSorted(toSerialize, function(value, key) {
9523                     serialize(value, prefix +
9524                         (topLevel ? '' : '[') +
9525                         key +
9526                         (topLevel ? '' : ']'));
9527                   });
9528                 } else {
9529                   parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
9530                 }
9531               }
9532             };
9533           };
9534         }
9535
9536         function defaultHttpResponseTransform(data, headers) {
9537           if (isString(data)) {
9538             // Strip json vulnerability protection prefix and trim whitespace
9539             var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
9540
9541             if (tempData) {
9542               var contentType = headers('Content-Type');
9543               if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
9544                 data = fromJson(tempData);
9545               }
9546             }
9547           }
9548
9549           return data;
9550         }
9551
9552         function isJsonLike(str) {
9553             var jsonStart = str.match(JSON_START);
9554             return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
9555         }
9556
9557         /**
9558          * Parse headers into key value object
9559          *
9560          * @param {string} headers Raw headers as a string
9561          * @returns {Object} Parsed headers as key value object
9562          */
9563         function parseHeaders(headers) {
9564           var parsed = createMap(), i;
9565
9566           function fillInParsed(key, val) {
9567             if (key) {
9568               parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
9569             }
9570           }
9571
9572           if (isString(headers)) {
9573             forEach(headers.split('\n'), function(line) {
9574               i = line.indexOf(':');
9575               fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1)));
9576             });
9577           } else if (isObject(headers)) {
9578             forEach(headers, function(headerVal, headerKey) {
9579               fillInParsed(lowercase(headerKey), trim(headerVal));
9580             });
9581           }
9582
9583           return parsed;
9584         }
9585
9586
9587         /**
9588          * Returns a function that provides access to parsed headers.
9589          *
9590          * Headers are lazy parsed when first requested.
9591          * @see parseHeaders
9592          *
9593          * @param {(string|Object)} headers Headers to provide access to.
9594          * @returns {function(string=)} Returns a getter function which if called with:
9595          *
9596          *   - if called with single an argument returns a single header value or null
9597          *   - if called with no arguments returns an object containing all headers.
9598          */
9599         function headersGetter(headers) {
9600           var headersObj;
9601
9602           return function(name) {
9603             if (!headersObj) headersObj =  parseHeaders(headers);
9604
9605             if (name) {
9606               var value = headersObj[lowercase(name)];
9607               if (value === void 0) {
9608                 value = null;
9609               }
9610               return value;
9611             }
9612
9613             return headersObj;
9614           };
9615         }
9616
9617
9618         /**
9619          * Chain all given functions
9620          *
9621          * This function is used for both request and response transforming
9622          *
9623          * @param {*} data Data to transform.
9624          * @param {function(string=)} headers HTTP headers getter fn.
9625          * @param {number} status HTTP status code of the response.
9626          * @param {(Function|Array.<Function>)} fns Function or an array of functions.
9627          * @returns {*} Transformed data.
9628          */
9629         function transformData(data, headers, status, fns) {
9630           if (isFunction(fns)) {
9631             return fns(data, headers, status);
9632           }
9633
9634           forEach(fns, function(fn) {
9635             data = fn(data, headers, status);
9636           });
9637
9638           return data;
9639         }
9640
9641
9642         function isSuccess(status) {
9643           return 200 <= status && status < 300;
9644         }
9645
9646
9647         /**
9648          * @ngdoc provider
9649          * @name $httpProvider
9650          * @description
9651          * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
9652          * */
9653         function $HttpProvider() {
9654           /**
9655            * @ngdoc property
9656            * @name $httpProvider#defaults
9657            * @description
9658            *
9659            * Object containing default values for all {@link ng.$http $http} requests.
9660            *
9661            * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
9662            * that will provide the cache for all requests who set their `cache` property to `true`.
9663            * If you set the `defaults.cache = false` then only requests that specify their own custom
9664            * cache object will be cached. See {@link $http#caching $http Caching} for more information.
9665            *
9666            * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
9667            * Defaults value is `'XSRF-TOKEN'`.
9668            *
9669            * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
9670            * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
9671            *
9672            * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
9673            * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
9674            * setting default headers.
9675            *     - **`defaults.headers.common`**
9676            *     - **`defaults.headers.post`**
9677            *     - **`defaults.headers.put`**
9678            *     - **`defaults.headers.patch`**
9679            *
9680            *
9681            * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function
9682            *  used to the prepare string representation of request parameters (specified as an object).
9683            *  If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
9684            *  Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
9685            *
9686            **/
9687           var defaults = this.defaults = {
9688             // transform incoming response data
9689             transformResponse: [defaultHttpResponseTransform],
9690
9691             // transform outgoing request data
9692             transformRequest: [function(d) {
9693               return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
9694             }],
9695
9696             // default headers
9697             headers: {
9698               common: {
9699                 'Accept': 'application/json, text/plain, */*'
9700               },
9701               post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
9702               put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
9703               patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
9704             },
9705
9706             xsrfCookieName: 'XSRF-TOKEN',
9707             xsrfHeaderName: 'X-XSRF-TOKEN',
9708
9709             paramSerializer: '$httpParamSerializer'
9710           };
9711
9712           var useApplyAsync = false;
9713           /**
9714            * @ngdoc method
9715            * @name $httpProvider#useApplyAsync
9716            * @description
9717            *
9718            * Configure $http service to combine processing of multiple http responses received at around
9719            * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in
9720            * significant performance improvement for bigger applications that make many HTTP requests
9721            * concurrently (common during application bootstrap).
9722            *
9723            * Defaults to false. If no value is specified, returns the current configured value.
9724            *
9725            * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred
9726            *    "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window
9727            *    to load and share the same digest cycle.
9728            *
9729            * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
9730            *    otherwise, returns the current configured value.
9731            **/
9732           this.useApplyAsync = function(value) {
9733             if (isDefined(value)) {
9734               useApplyAsync = !!value;
9735               return this;
9736             }
9737             return useApplyAsync;
9738           };
9739
9740           var useLegacyPromise = true;
9741           /**
9742            * @ngdoc method
9743            * @name $httpProvider#useLegacyPromiseExtensions
9744            * @description
9745            *
9746            * Configure `$http` service to return promises without the shorthand methods `success` and `error`.
9747            * This should be used to make sure that applications work without these methods.
9748            *
9749            * Defaults to true. If no value is specified, returns the current configured value.
9750            *
9751            * @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods.
9752            *
9753            * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
9754            *    otherwise, returns the current configured value.
9755            **/
9756           this.useLegacyPromiseExtensions = function(value) {
9757             if (isDefined(value)) {
9758               useLegacyPromise = !!value;
9759               return this;
9760             }
9761             return useLegacyPromise;
9762           };
9763
9764           /**
9765            * @ngdoc property
9766            * @name $httpProvider#interceptors
9767            * @description
9768            *
9769            * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
9770            * pre-processing of request or postprocessing of responses.
9771            *
9772            * These service factories are ordered by request, i.e. they are applied in the same order as the
9773            * array, on request, but reverse order, on response.
9774            *
9775            * {@link ng.$http#interceptors Interceptors detailed info}
9776            **/
9777           var interceptorFactories = this.interceptors = [];
9778
9779           this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
9780               function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
9781
9782             var defaultCache = $cacheFactory('$http');
9783
9784             /**
9785              * Make sure that default param serializer is exposed as a function
9786              */
9787             defaults.paramSerializer = isString(defaults.paramSerializer) ?
9788               $injector.get(defaults.paramSerializer) : defaults.paramSerializer;
9789
9790             /**
9791              * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
9792              * The reversal is needed so that we can build up the interception chain around the
9793              * server request.
9794              */
9795             var reversedInterceptors = [];
9796
9797             forEach(interceptorFactories, function(interceptorFactory) {
9798               reversedInterceptors.unshift(isString(interceptorFactory)
9799                   ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
9800             });
9801
9802             /**
9803              * @ngdoc service
9804              * @kind function
9805              * @name $http
9806              * @requires ng.$httpBackend
9807              * @requires $cacheFactory
9808              * @requires $rootScope
9809              * @requires $q
9810              * @requires $injector
9811              *
9812              * @description
9813              * The `$http` service is a core Angular service that facilitates communication with the remote
9814              * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
9815              * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
9816              *
9817              * For unit testing applications that use `$http` service, see
9818              * {@link ngMock.$httpBackend $httpBackend mock}.
9819              *
9820              * For a higher level of abstraction, please check out the {@link ngResource.$resource
9821              * $resource} service.
9822              *
9823              * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
9824              * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
9825              * it is important to familiarize yourself with these APIs and the guarantees they provide.
9826              *
9827              *
9828              * ## General usage
9829              * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} —
9830              * that is used to generate an HTTP request and returns  a {@link ng.$q promise}.
9831              *
9832              * ```js
9833              *   // Simple GET request example:
9834              *   $http({
9835              *     method: 'GET',
9836              *     url: '/someUrl'
9837              *   }).then(function successCallback(response) {
9838              *       // this callback will be called asynchronously
9839              *       // when the response is available
9840              *     }, function errorCallback(response) {
9841              *       // called asynchronously if an error occurs
9842              *       // or server returns response with an error status.
9843              *     });
9844              * ```
9845              *
9846              * The response object has these properties:
9847              *
9848              *   - **data** – `{string|Object}` – The response body transformed with the transform
9849              *     functions.
9850              *   - **status** – `{number}` – HTTP status code of the response.
9851              *   - **headers** – `{function([headerName])}` – Header getter function.
9852              *   - **config** – `{Object}` – The configuration object that was used to generate the request.
9853              *   - **statusText** – `{string}` – HTTP status text of the response.
9854              *
9855              * A response status code between 200 and 299 is considered a success status and
9856              * will result in the success callback being called. Note that if the response is a redirect,
9857              * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
9858              * called for such responses.
9859              *
9860              *
9861              * ## Shortcut methods
9862              *
9863              * Shortcut methods are also available. All shortcut methods require passing in the URL, and
9864              * request data must be passed in for POST/PUT requests. An optional config can be passed as the
9865              * last argument.
9866              *
9867              * ```js
9868              *   $http.get('/someUrl', config).then(successCallback, errorCallback);
9869              *   $http.post('/someUrl', data, config).then(successCallback, errorCallback);
9870              * ```
9871              *
9872              * Complete list of shortcut methods:
9873              *
9874              * - {@link ng.$http#get $http.get}
9875              * - {@link ng.$http#head $http.head}
9876              * - {@link ng.$http#post $http.post}
9877              * - {@link ng.$http#put $http.put}
9878              * - {@link ng.$http#delete $http.delete}
9879              * - {@link ng.$http#jsonp $http.jsonp}
9880              * - {@link ng.$http#patch $http.patch}
9881              *
9882              *
9883              * ## Writing Unit Tests that use $http
9884              * When unit testing (using {@link ngMock ngMock}), it is necessary to call
9885              * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
9886              * request using trained responses.
9887              *
9888              * ```
9889              * $httpBackend.expectGET(...);
9890              * $http.get(...);
9891              * $httpBackend.flush();
9892              * ```
9893              *
9894              * ## Deprecation Notice
9895              * <div class="alert alert-danger">
9896              *   The `$http` legacy promise methods `success` and `error` have been deprecated.
9897              *   Use the standard `then` method instead.
9898              *   If {@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`} is set to
9899              *   `false` then these methods will throw {@link $http:legacy `$http/legacy`} error.
9900              * </div>
9901              *
9902              * ## Setting HTTP Headers
9903              *
9904              * The $http service will automatically add certain HTTP headers to all requests. These defaults
9905              * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
9906              * object, which currently contains this default configuration:
9907              *
9908              * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
9909              *   - `Accept: application/json, text/plain, * / *`
9910              * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
9911              *   - `Content-Type: application/json`
9912              * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
9913              *   - `Content-Type: application/json`
9914              *
9915              * To add or overwrite these defaults, simply add or remove a property from these configuration
9916              * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
9917              * with the lowercased HTTP method name as the key, e.g.
9918              * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`.
9919              *
9920              * The defaults can also be set at runtime via the `$http.defaults` object in the same
9921              * fashion. For example:
9922              *
9923              * ```
9924              * module.run(function($http) {
9925              *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
9926              * });
9927              * ```
9928              *
9929              * In addition, you can supply a `headers` property in the config object passed when
9930              * calling `$http(config)`, which overrides the defaults without changing them globally.
9931              *
9932              * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
9933              * Use the `headers` property, setting the desired header to `undefined`. For example:
9934              *
9935              * ```js
9936              * var req = {
9937              *  method: 'POST',
9938              *  url: 'http://example.com',
9939              *  headers: {
9940              *    'Content-Type': undefined
9941              *  },
9942              *  data: { test: 'test' }
9943              * }
9944              *
9945              * $http(req).then(function(){...}, function(){...});
9946              * ```
9947              *
9948              * ## Transforming Requests and Responses
9949              *
9950              * Both requests and responses can be transformed using transformation functions: `transformRequest`
9951              * and `transformResponse`. These properties can be a single function that returns
9952              * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,
9953              * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
9954              *
9955              * ### Default Transformations
9956              *
9957              * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
9958              * `defaults.transformResponse` properties. If a request does not provide its own transformations
9959              * then these will be applied.
9960              *
9961              * You can augment or replace the default transformations by modifying these properties by adding to or
9962              * replacing the array.
9963              *
9964              * Angular provides the following default transformations:
9965              *
9966              * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
9967              *
9968              * - If the `data` property of the request configuration object contains an object, serialize it
9969              *   into JSON format.
9970              *
9971              * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
9972              *
9973              *  - If XSRF prefix is detected, strip it (see Security Considerations section below).
9974              *  - If JSON response is detected, deserialize it using a JSON parser.
9975              *
9976              *
9977              * ### Overriding the Default Transformations Per Request
9978              *
9979              * If you wish override the request/response transformations only for a single request then provide
9980              * `transformRequest` and/or `transformResponse` properties on the configuration object passed
9981              * into `$http`.
9982              *
9983              * Note that if you provide these properties on the config object the default transformations will be
9984              * overwritten. If you wish to augment the default transformations then you must include them in your
9985              * local transformation array.
9986              *
9987              * The following code demonstrates adding a new response transformation to be run after the default response
9988              * transformations have been run.
9989              *
9990              * ```js
9991              * function appendTransform(defaults, transform) {
9992              *
9993              *   // We can't guarantee that the default transformation is an array
9994              *   defaults = angular.isArray(defaults) ? defaults : [defaults];
9995              *
9996              *   // Append the new transformation to the defaults
9997              *   return defaults.concat(transform);
9998              * }
9999              *
10000              * $http({
10001              *   url: '...',
10002              *   method: 'GET',
10003              *   transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
10004              *     return doTransform(value);
10005              *   })
10006              * });
10007              * ```
10008              *
10009              *
10010              * ## Caching
10011              *
10012              * To enable caching, set the request configuration `cache` property to `true` (to use default
10013              * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
10014              * When the cache is enabled, `$http` stores the response from the server in the specified
10015              * cache. The next time the same request is made, the response is served from the cache without
10016              * sending a request to the server.
10017              *
10018              * Note that even if the response is served from cache, delivery of the data is asynchronous in
10019              * the same way that real requests are.
10020              *
10021              * If there are multiple GET requests for the same URL that should be cached using the same
10022              * cache, but the cache is not populated yet, only one request to the server will be made and
10023              * the remaining requests will be fulfilled using the response from the first request.
10024              *
10025              * You can change the default cache to a new object (built with
10026              * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
10027              * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set
10028              * their `cache` property to `true` will now use this cache object.
10029              *
10030              * If you set the default cache to `false` then only requests that specify their own custom
10031              * cache object will be cached.
10032              *
10033              * ## Interceptors
10034              *
10035              * Before you start creating interceptors, be sure to understand the
10036              * {@link ng.$q $q and deferred/promise APIs}.
10037              *
10038              * For purposes of global error handling, authentication, or any kind of synchronous or
10039              * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
10040              * able to intercept requests before they are handed to the server and
10041              * responses before they are handed over to the application code that
10042              * initiated these requests. The interceptors leverage the {@link ng.$q
10043              * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
10044              *
10045              * The interceptors are service factories that are registered with the `$httpProvider` by
10046              * adding them to the `$httpProvider.interceptors` array. The factory is called and
10047              * injected with dependencies (if specified) and returns the interceptor.
10048              *
10049              * There are two kinds of interceptors (and two kinds of rejection interceptors):
10050              *
10051              *   * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to
10052              *     modify the `config` object or create a new one. The function needs to return the `config`
10053              *     object directly, or a promise containing the `config` or a new `config` object.
10054              *   * `requestError`: interceptor gets called when a previous interceptor threw an error or
10055              *     resolved with a rejection.
10056              *   * `response`: interceptors get called with http `response` object. The function is free to
10057              *     modify the `response` object or create a new one. The function needs to return the `response`
10058              *     object directly, or as a promise containing the `response` or a new `response` object.
10059              *   * `responseError`: interceptor gets called when a previous interceptor threw an error or
10060              *     resolved with a rejection.
10061              *
10062              *
10063              * ```js
10064              *   // register the interceptor as a service
10065              *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
10066              *     return {
10067              *       // optional method
10068              *       'request': function(config) {
10069              *         // do something on success
10070              *         return config;
10071              *       },
10072              *
10073              *       // optional method
10074              *      'requestError': function(rejection) {
10075              *         // do something on error
10076              *         if (canRecover(rejection)) {
10077              *           return responseOrNewPromise
10078              *         }
10079              *         return $q.reject(rejection);
10080              *       },
10081              *
10082              *
10083              *
10084              *       // optional method
10085              *       'response': function(response) {
10086              *         // do something on success
10087              *         return response;
10088              *       },
10089              *
10090              *       // optional method
10091              *      'responseError': function(rejection) {
10092              *         // do something on error
10093              *         if (canRecover(rejection)) {
10094              *           return responseOrNewPromise
10095              *         }
10096              *         return $q.reject(rejection);
10097              *       }
10098              *     };
10099              *   });
10100              *
10101              *   $httpProvider.interceptors.push('myHttpInterceptor');
10102              *
10103              *
10104              *   // alternatively, register the interceptor via an anonymous factory
10105              *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
10106              *     return {
10107              *      'request': function(config) {
10108              *          // same as above
10109              *       },
10110              *
10111              *       'response': function(response) {
10112              *          // same as above
10113              *       }
10114              *     };
10115              *   });
10116              * ```
10117              *
10118              * ## Security Considerations
10119              *
10120              * When designing web applications, consider security threats from:
10121              *
10122              * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
10123              * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
10124              *
10125              * Both server and the client must cooperate in order to eliminate these threats. Angular comes
10126              * pre-configured with strategies that address these issues, but for this to work backend server
10127              * cooperation is required.
10128              *
10129              * ### JSON Vulnerability Protection
10130              *
10131              * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
10132              * allows third party website to turn your JSON resource URL into
10133              * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
10134              * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
10135              * Angular will automatically strip the prefix before processing it as JSON.
10136              *
10137              * For example if your server needs to return:
10138              * ```js
10139              * ['one','two']
10140              * ```
10141              *
10142              * which is vulnerable to attack, your server can return:
10143              * ```js
10144              * )]}',
10145              * ['one','two']
10146              * ```
10147              *
10148              * Angular will strip the prefix, before processing the JSON.
10149              *
10150              *
10151              * ### Cross Site Request Forgery (XSRF) Protection
10152              *
10153              * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
10154              * an unauthorized site can gain your user's private data. Angular provides a mechanism
10155              * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
10156              * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
10157              * JavaScript that runs on your domain could read the cookie, your server can be assured that
10158              * the XHR came from JavaScript running on your domain. The header will not be set for
10159              * cross-domain requests.
10160              *
10161              * To take advantage of this, your server needs to set a token in a JavaScript readable session
10162              * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
10163              * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
10164              * that only JavaScript running on your domain could have sent the request. The token must be
10165              * unique for each user and must be verifiable by the server (to prevent the JavaScript from
10166              * making up its own tokens). We recommend that the token is a digest of your site's
10167              * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
10168              * for added security.
10169              *
10170              * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
10171              * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
10172              * or the per-request config object.
10173              *
10174              * In order to prevent collisions in environments where multiple Angular apps share the
10175              * same domain or subdomain, we recommend that each application uses unique cookie name.
10176              *
10177              * @param {object} config Object describing the request to be made and how it should be
10178              *    processed. The object has following properties:
10179              *
10180              *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
10181              *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
10182              *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized
10183              *      with the `paramSerializer` and appended as GET parameters.
10184              *    - **data** – `{string|Object}` – Data to be sent as the request message data.
10185              *    - **headers** – `{Object}` – Map of strings or functions which return strings representing
10186              *      HTTP headers to send to the server. If the return value of a function is null, the
10187              *      header will not be sent. Functions accept a config object as an argument.
10188              *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
10189              *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
10190              *    - **transformRequest** –
10191              *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
10192              *      transform function or an array of such functions. The transform function takes the http
10193              *      request body and headers and returns its transformed (typically serialized) version.
10194              *      See {@link ng.$http#overriding-the-default-transformations-per-request
10195              *      Overriding the Default Transformations}
10196              *    - **transformResponse** –
10197              *      `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
10198              *      transform function or an array of such functions. The transform function takes the http
10199              *      response body, headers and status and returns its transformed (typically deserialized) version.
10200              *      See {@link ng.$http#overriding-the-default-transformations-per-request
10201              *      Overriding the Default TransformationjqLiks}
10202              *    - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to
10203              *      prepare the string representation of request parameters (specified as an object).
10204              *      If specified as string, it is interpreted as function registered with the
10205              *      {@link $injector $injector}, which means you can create your own serializer
10206              *      by registering it as a {@link auto.$provide#service service}.
10207              *      The default serializer is the {@link $httpParamSerializer $httpParamSerializer};
10208              *      alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}
10209              *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
10210              *      GET request, otherwise if a cache instance built with
10211              *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
10212              *      caching.
10213              *    - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
10214              *      that should abort the request when resolved.
10215              *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
10216              *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
10217              *      for more information.
10218              *    - **responseType** - `{string}` - see
10219              *      [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
10220              *
10221              * @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object
10222              *                        when the request succeeds or fails.
10223              *
10224              *
10225              * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
10226              *   requests. This is primarily meant to be used for debugging purposes.
10227              *
10228              *
10229              * @example
10230         <example module="httpExample">
10231         <file name="index.html">
10232           <div ng-controller="FetchController">
10233             <select ng-model="method" aria-label="Request method">
10234               <option>GET</option>
10235               <option>JSONP</option>
10236             </select>
10237             <input type="text" ng-model="url" size="80" aria-label="URL" />
10238             <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
10239             <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
10240             <button id="samplejsonpbtn"
10241               ng-click="updateModel('JSONP',
10242                             'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
10243               Sample JSONP
10244             </button>
10245             <button id="invalidjsonpbtn"
10246               ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
10247                 Invalid JSONP
10248               </button>
10249             <pre>http status code: {{status}}</pre>
10250             <pre>http response data: {{data}}</pre>
10251           </div>
10252         </file>
10253         <file name="script.js">
10254           angular.module('httpExample', [])
10255             .controller('FetchController', ['$scope', '$http', '$templateCache',
10256               function($scope, $http, $templateCache) {
10257                 $scope.method = 'GET';
10258                 $scope.url = 'http-hello.html';
10259
10260                 $scope.fetch = function() {
10261                   $scope.code = null;
10262                   $scope.response = null;
10263
10264                   $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
10265                     then(function(response) {
10266                       $scope.status = response.status;
10267                       $scope.data = response.data;
10268                     }, function(response) {
10269                       $scope.data = response.data || "Request failed";
10270                       $scope.status = response.status;
10271                   });
10272                 };
10273
10274                 $scope.updateModel = function(method, url) {
10275                   $scope.method = method;
10276                   $scope.url = url;
10277                 };
10278               }]);
10279         </file>
10280         <file name="http-hello.html">
10281           Hello, $http!
10282         </file>
10283         <file name="protractor.js" type="protractor">
10284           var status = element(by.binding('status'));
10285           var data = element(by.binding('data'));
10286           var fetchBtn = element(by.id('fetchbtn'));
10287           var sampleGetBtn = element(by.id('samplegetbtn'));
10288           var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
10289           var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));
10290
10291           it('should make an xhr GET request', function() {
10292             sampleGetBtn.click();
10293             fetchBtn.click();
10294             expect(status.getText()).toMatch('200');
10295             expect(data.getText()).toMatch(/Hello, \$http!/);
10296           });
10297
10298         // Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185
10299         // it('should make a JSONP request to angularjs.org', function() {
10300         //   sampleJsonpBtn.click();
10301         //   fetchBtn.click();
10302         //   expect(status.getText()).toMatch('200');
10303         //   expect(data.getText()).toMatch(/Super Hero!/);
10304         // });
10305
10306           it('should make JSONP request to invalid URL and invoke the error handler',
10307               function() {
10308             invalidJsonpBtn.click();
10309             fetchBtn.click();
10310             expect(status.getText()).toMatch('0');
10311             expect(data.getText()).toMatch('Request failed');
10312           });
10313         </file>
10314         </example>
10315              */
10316             function $http(requestConfig) {
10317
10318               if (!angular.isObject(requestConfig)) {
10319                 throw minErr('$http')('badreq', 'Http request configuration must be an object.  Received: {0}', requestConfig);
10320               }
10321
10322               var config = extend({
10323                 method: 'get',
10324                 transformRequest: defaults.transformRequest,
10325                 transformResponse: defaults.transformResponse,
10326                 paramSerializer: defaults.paramSerializer
10327               }, requestConfig);
10328
10329               config.headers = mergeHeaders(requestConfig);
10330               config.method = uppercase(config.method);
10331               config.paramSerializer = isString(config.paramSerializer) ?
10332                 $injector.get(config.paramSerializer) : config.paramSerializer;
10333
10334               var serverRequest = function(config) {
10335                 var headers = config.headers;
10336                 var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
10337
10338                 // strip content-type if data is undefined
10339                 if (isUndefined(reqData)) {
10340                   forEach(headers, function(value, header) {
10341                     if (lowercase(header) === 'content-type') {
10342                         delete headers[header];
10343                     }
10344                   });
10345                 }
10346
10347                 if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
10348                   config.withCredentials = defaults.withCredentials;
10349                 }
10350
10351                 // send request
10352                 return sendReq(config, reqData).then(transformResponse, transformResponse);
10353               };
10354
10355               var chain = [serverRequest, undefined];
10356               var promise = $q.when(config);
10357
10358               // apply interceptors
10359               forEach(reversedInterceptors, function(interceptor) {
10360                 if (interceptor.request || interceptor.requestError) {
10361                   chain.unshift(interceptor.request, interceptor.requestError);
10362                 }
10363                 if (interceptor.response || interceptor.responseError) {
10364                   chain.push(interceptor.response, interceptor.responseError);
10365                 }
10366               });
10367
10368               while (chain.length) {
10369                 var thenFn = chain.shift();
10370                 var rejectFn = chain.shift();
10371
10372                 promise = promise.then(thenFn, rejectFn);
10373               }
10374
10375               if (useLegacyPromise) {
10376                 promise.success = function(fn) {
10377                   assertArgFn(fn, 'fn');
10378
10379                   promise.then(function(response) {
10380                     fn(response.data, response.status, response.headers, config);
10381                   });
10382                   return promise;
10383                 };
10384
10385                 promise.error = function(fn) {
10386                   assertArgFn(fn, 'fn');
10387
10388                   promise.then(null, function(response) {
10389                     fn(response.data, response.status, response.headers, config);
10390                   });
10391                   return promise;
10392                 };
10393               } else {
10394                 promise.success = $httpMinErrLegacyFn('success');
10395                 promise.error = $httpMinErrLegacyFn('error');
10396               }
10397
10398               return promise;
10399
10400               function transformResponse(response) {
10401                 // make a copy since the response must be cacheable
10402                 var resp = extend({}, response);
10403                 resp.data = transformData(response.data, response.headers, response.status,
10404                                           config.transformResponse);
10405                 return (isSuccess(response.status))
10406                   ? resp
10407                   : $q.reject(resp);
10408               }
10409
10410               function executeHeaderFns(headers, config) {
10411                 var headerContent, processedHeaders = {};
10412
10413                 forEach(headers, function(headerFn, header) {
10414                   if (isFunction(headerFn)) {
10415                     headerContent = headerFn(config);
10416                     if (headerContent != null) {
10417                       processedHeaders[header] = headerContent;
10418                     }
10419                   } else {
10420                     processedHeaders[header] = headerFn;
10421                   }
10422                 });
10423
10424                 return processedHeaders;
10425               }
10426
10427               function mergeHeaders(config) {
10428                 var defHeaders = defaults.headers,
10429                     reqHeaders = extend({}, config.headers),
10430                     defHeaderName, lowercaseDefHeaderName, reqHeaderName;
10431
10432                 defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
10433
10434                 // using for-in instead of forEach to avoid unecessary iteration after header has been found
10435                 defaultHeadersIteration:
10436                 for (defHeaderName in defHeaders) {
10437                   lowercaseDefHeaderName = lowercase(defHeaderName);
10438
10439                   for (reqHeaderName in reqHeaders) {
10440                     if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
10441                       continue defaultHeadersIteration;
10442                     }
10443                   }
10444
10445                   reqHeaders[defHeaderName] = defHeaders[defHeaderName];
10446                 }
10447
10448                 // execute if header value is a function for merged headers
10449                 return executeHeaderFns(reqHeaders, shallowCopy(config));
10450               }
10451             }
10452
10453             $http.pendingRequests = [];
10454
10455             /**
10456              * @ngdoc method
10457              * @name $http#get
10458              *
10459              * @description
10460              * Shortcut method to perform `GET` request.
10461              *
10462              * @param {string} url Relative or absolute URL specifying the destination of the request
10463              * @param {Object=} config Optional configuration object
10464              * @returns {HttpPromise} Future object
10465              */
10466
10467             /**
10468              * @ngdoc method
10469              * @name $http#delete
10470              *
10471              * @description
10472              * Shortcut method to perform `DELETE` request.
10473              *
10474              * @param {string} url Relative or absolute URL specifying the destination of the request
10475              * @param {Object=} config Optional configuration object
10476              * @returns {HttpPromise} Future object
10477              */
10478
10479             /**
10480              * @ngdoc method
10481              * @name $http#head
10482              *
10483              * @description
10484              * Shortcut method to perform `HEAD` request.
10485              *
10486              * @param {string} url Relative or absolute URL specifying the destination of the request
10487              * @param {Object=} config Optional configuration object
10488              * @returns {HttpPromise} Future object
10489              */
10490
10491             /**
10492              * @ngdoc method
10493              * @name $http#jsonp
10494              *
10495              * @description
10496              * Shortcut method to perform `JSONP` request.
10497              *
10498              * @param {string} url Relative or absolute URL specifying the destination of the request.
10499              *                     The name of the callback should be the string `JSON_CALLBACK`.
10500              * @param {Object=} config Optional configuration object
10501              * @returns {HttpPromise} Future object
10502              */
10503             createShortMethods('get', 'delete', 'head', 'jsonp');
10504
10505             /**
10506              * @ngdoc method
10507              * @name $http#post
10508              *
10509              * @description
10510              * Shortcut method to perform `POST` request.
10511              *
10512              * @param {string} url Relative or absolute URL specifying the destination of the request
10513              * @param {*} data Request content
10514              * @param {Object=} config Optional configuration object
10515              * @returns {HttpPromise} Future object
10516              */
10517
10518             /**
10519              * @ngdoc method
10520              * @name $http#put
10521              *
10522              * @description
10523              * Shortcut method to perform `PUT` request.
10524              *
10525              * @param {string} url Relative or absolute URL specifying the destination of the request
10526              * @param {*} data Request content
10527              * @param {Object=} config Optional configuration object
10528              * @returns {HttpPromise} Future object
10529              */
10530
10531              /**
10532               * @ngdoc method
10533               * @name $http#patch
10534               *
10535               * @description
10536               * Shortcut method to perform `PATCH` request.
10537               *
10538               * @param {string} url Relative or absolute URL specifying the destination of the request
10539               * @param {*} data Request content
10540               * @param {Object=} config Optional configuration object
10541               * @returns {HttpPromise} Future object
10542               */
10543             createShortMethodsWithData('post', 'put', 'patch');
10544
10545                 /**
10546                  * @ngdoc property
10547                  * @name $http#defaults
10548                  *
10549                  * @description
10550                  * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
10551                  * default headers, withCredentials as well as request and response transformations.
10552                  *
10553                  * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
10554                  */
10555             $http.defaults = defaults;
10556
10557
10558             return $http;
10559
10560
10561             function createShortMethods(names) {
10562               forEach(arguments, function(name) {
10563                 $http[name] = function(url, config) {
10564                   return $http(extend({}, config || {}, {
10565                     method: name,
10566                     url: url
10567                   }));
10568                 };
10569               });
10570             }
10571
10572
10573             function createShortMethodsWithData(name) {
10574               forEach(arguments, function(name) {
10575                 $http[name] = function(url, data, config) {
10576                   return $http(extend({}, config || {}, {
10577                     method: name,
10578                     url: url,
10579                     data: data
10580                   }));
10581                 };
10582               });
10583             }
10584
10585
10586             /**
10587              * Makes the request.
10588              *
10589              * !!! ACCESSES CLOSURE VARS:
10590              * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
10591              */
10592             function sendReq(config, reqData) {
10593               var deferred = $q.defer(),
10594                   promise = deferred.promise,
10595                   cache,
10596                   cachedResp,
10597                   reqHeaders = config.headers,
10598                   url = buildUrl(config.url, config.paramSerializer(config.params));
10599
10600               $http.pendingRequests.push(config);
10601               promise.then(removePendingReq, removePendingReq);
10602
10603
10604               if ((config.cache || defaults.cache) && config.cache !== false &&
10605                   (config.method === 'GET' || config.method === 'JSONP')) {
10606                 cache = isObject(config.cache) ? config.cache
10607                       : isObject(defaults.cache) ? defaults.cache
10608                       : defaultCache;
10609               }
10610
10611               if (cache) {
10612                 cachedResp = cache.get(url);
10613                 if (isDefined(cachedResp)) {
10614                   if (isPromiseLike(cachedResp)) {
10615                     // cached request has already been sent, but there is no response yet
10616                     cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
10617                   } else {
10618                     // serving from cache
10619                     if (isArray(cachedResp)) {
10620                       resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
10621                     } else {
10622                       resolvePromise(cachedResp, 200, {}, 'OK');
10623                     }
10624                   }
10625                 } else {
10626                   // put the promise for the non-transformed response into cache as a placeholder
10627                   cache.put(url, promise);
10628                 }
10629               }
10630
10631
10632               // if we won't have the response in cache, set the xsrf headers and
10633               // send the request to the backend
10634               if (isUndefined(cachedResp)) {
10635                 var xsrfValue = urlIsSameOrigin(config.url)
10636                     ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
10637                     : undefined;
10638                 if (xsrfValue) {
10639                   reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
10640                 }
10641
10642                 $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
10643                     config.withCredentials, config.responseType);
10644               }
10645
10646               return promise;
10647
10648
10649               /**
10650                * Callback registered to $httpBackend():
10651                *  - caches the response if desired
10652                *  - resolves the raw $http promise
10653                *  - calls $apply
10654                */
10655               function done(status, response, headersString, statusText) {
10656                 if (cache) {
10657                   if (isSuccess(status)) {
10658                     cache.put(url, [status, response, parseHeaders(headersString), statusText]);
10659                   } else {
10660                     // remove promise from the cache
10661                     cache.remove(url);
10662                   }
10663                 }
10664
10665                 function resolveHttpPromise() {
10666                   resolvePromise(response, status, headersString, statusText);
10667                 }
10668
10669                 if (useApplyAsync) {
10670                   $rootScope.$applyAsync(resolveHttpPromise);
10671                 } else {
10672                   resolveHttpPromise();
10673                   if (!$rootScope.$$phase) $rootScope.$apply();
10674                 }
10675               }
10676
10677
10678               /**
10679                * Resolves the raw $http promise.
10680                */
10681               function resolvePromise(response, status, headers, statusText) {
10682                 //status: HTTP response status code, 0, -1 (aborted by timeout / promise)
10683                 status = status >= -1 ? status : 0;
10684
10685                 (isSuccess(status) ? deferred.resolve : deferred.reject)({
10686                   data: response,
10687                   status: status,
10688                   headers: headersGetter(headers),
10689                   config: config,
10690                   statusText: statusText
10691                 });
10692               }
10693
10694               function resolvePromiseWithResult(result) {
10695                 resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
10696               }
10697
10698               function removePendingReq() {
10699                 var idx = $http.pendingRequests.indexOf(config);
10700                 if (idx !== -1) $http.pendingRequests.splice(idx, 1);
10701               }
10702             }
10703
10704
10705             function buildUrl(url, serializedParams) {
10706               if (serializedParams.length > 0) {
10707                 url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams;
10708               }
10709               return url;
10710             }
10711           }];
10712         }
10713
10714         /**
10715          * @ngdoc service
10716          * @name $xhrFactory
10717          *
10718          * @description
10719          * Factory function used to create XMLHttpRequest objects.
10720          *
10721          * Replace or decorate this service to create your own custom XMLHttpRequest objects.
10722          *
10723          * ```
10724          * angular.module('myApp', [])
10725          * .factory('$xhrFactory', function() {
10726          *   return function createXhr(method, url) {
10727          *     return new window.XMLHttpRequest({mozSystem: true});
10728          *   };
10729          * });
10730          * ```
10731          *
10732          * @param {string} method HTTP method of the request (GET, POST, PUT, ..)
10733          * @param {string} url URL of the request.
10734          */
10735         function $xhrFactoryProvider() {
10736           this.$get = function() {
10737             return function createXhr() {
10738               return new window.XMLHttpRequest();
10739             };
10740           };
10741         }
10742
10743         /**
10744          * @ngdoc service
10745          * @name $httpBackend
10746          * @requires $window
10747          * @requires $document
10748          * @requires $xhrFactory
10749          *
10750          * @description
10751          * HTTP backend used by the {@link ng.$http service} that delegates to
10752          * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
10753          *
10754          * You should never need to use this service directly, instead use the higher-level abstractions:
10755          * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
10756          *
10757          * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
10758          * $httpBackend} which can be trained with responses.
10759          */
10760         function $HttpBackendProvider() {
10761           this.$get = ['$browser', '$window', '$document', '$xhrFactory', function($browser, $window, $document, $xhrFactory) {
10762             return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]);
10763           }];
10764         }
10765
10766         function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
10767           // TODO(vojta): fix the signature
10768           return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
10769             $browser.$$incOutstandingRequestCount();
10770             url = url || $browser.url();
10771
10772             if (lowercase(method) == 'jsonp') {
10773               var callbackId = '_' + (callbacks.counter++).toString(36);
10774               callbacks[callbackId] = function(data) {
10775                 callbacks[callbackId].data = data;
10776                 callbacks[callbackId].called = true;
10777               };
10778
10779               var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
10780                   callbackId, function(status, text) {
10781                 completeRequest(callback, status, callbacks[callbackId].data, "", text);
10782                 callbacks[callbackId] = noop;
10783               });
10784             } else {
10785
10786               var xhr = createXhr(method, url);
10787
10788               xhr.open(method, url, true);
10789               forEach(headers, function(value, key) {
10790                 if (isDefined(value)) {
10791                     xhr.setRequestHeader(key, value);
10792                 }
10793               });
10794
10795               xhr.onload = function requestLoaded() {
10796                 var statusText = xhr.statusText || '';
10797
10798                 // responseText is the old-school way of retrieving response (supported by IE9)
10799                 // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
10800                 var response = ('response' in xhr) ? xhr.response : xhr.responseText;
10801
10802                 // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
10803                 var status = xhr.status === 1223 ? 204 : xhr.status;
10804
10805                 // fix status code when it is 0 (0 status is undocumented).
10806                 // Occurs when accessing file resources or on Android 4.1 stock browser
10807                 // while retrieving files from application cache.
10808                 if (status === 0) {
10809                   status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
10810                 }
10811
10812                 completeRequest(callback,
10813                     status,
10814                     response,
10815                     xhr.getAllResponseHeaders(),
10816                     statusText);
10817               };
10818
10819               var requestError = function() {
10820                 // The response is always empty
10821                 // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
10822                 completeRequest(callback, -1, null, null, '');
10823               };
10824
10825               xhr.onerror = requestError;
10826               xhr.onabort = requestError;
10827
10828               if (withCredentials) {
10829                 xhr.withCredentials = true;
10830               }
10831
10832               if (responseType) {
10833                 try {
10834                   xhr.responseType = responseType;
10835                 } catch (e) {
10836                   // WebKit added support for the json responseType value on 09/03/2013
10837                   // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
10838                   // known to throw when setting the value "json" as the response type. Other older
10839                   // browsers implementing the responseType
10840                   //
10841                   // The json response type can be ignored if not supported, because JSON payloads are
10842                   // parsed on the client-side regardless.
10843                   if (responseType !== 'json') {
10844                     throw e;
10845                   }
10846                 }
10847               }
10848
10849               xhr.send(isUndefined(post) ? null : post);
10850             }
10851
10852             if (timeout > 0) {
10853               var timeoutId = $browserDefer(timeoutRequest, timeout);
10854             } else if (isPromiseLike(timeout)) {
10855               timeout.then(timeoutRequest);
10856             }
10857
10858
10859             function timeoutRequest() {
10860               jsonpDone && jsonpDone();
10861               xhr && xhr.abort();
10862             }
10863
10864             function completeRequest(callback, status, response, headersString, statusText) {
10865               // cancel timeout and subsequent timeout promise resolution
10866               if (isDefined(timeoutId)) {
10867                 $browserDefer.cancel(timeoutId);
10868               }
10869               jsonpDone = xhr = null;
10870
10871               callback(status, response, headersString, statusText);
10872               $browser.$$completeOutstandingRequest(noop);
10873             }
10874           };
10875
10876           function jsonpReq(url, callbackId, done) {
10877             // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
10878             // - fetches local scripts via XHR and evals them
10879             // - adds and immediately removes script elements from the document
10880             var script = rawDocument.createElement('script'), callback = null;
10881             script.type = "text/javascript";
10882             script.src = url;
10883             script.async = true;
10884
10885             callback = function(event) {
10886               removeEventListenerFn(script, "load", callback);
10887               removeEventListenerFn(script, "error", callback);
10888               rawDocument.body.removeChild(script);
10889               script = null;
10890               var status = -1;
10891               var text = "unknown";
10892
10893               if (event) {
10894                 if (event.type === "load" && !callbacks[callbackId].called) {
10895                   event = { type: "error" };
10896                 }
10897                 text = event.type;
10898                 status = event.type === "error" ? 404 : 200;
10899               }
10900
10901               if (done) {
10902                 done(status, text);
10903               }
10904             };
10905
10906             addEventListenerFn(script, "load", callback);
10907             addEventListenerFn(script, "error", callback);
10908             rawDocument.body.appendChild(script);
10909             return callback;
10910           }
10911         }
10912
10913         var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate');
10914         $interpolateMinErr.throwNoconcat = function(text) {
10915           throw $interpolateMinErr('noconcat',
10916               "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
10917               "interpolations that concatenate multiple expressions when a trusted value is " +
10918               "required.  See http://docs.angularjs.org/api/ng.$sce", text);
10919         };
10920
10921         $interpolateMinErr.interr = function(text, err) {
10922           return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString());
10923         };
10924
10925         /**
10926          * @ngdoc provider
10927          * @name $interpolateProvider
10928          *
10929          * @description
10930          *
10931          * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
10932          *
10933          * @example
10934         <example module="customInterpolationApp">
10935         <file name="index.html">
10936         <script>
10937           var customInterpolationApp = angular.module('customInterpolationApp', []);
10938
10939           customInterpolationApp.config(function($interpolateProvider) {
10940             $interpolateProvider.startSymbol('//');
10941             $interpolateProvider.endSymbol('//');
10942           });
10943
10944
10945           customInterpolationApp.controller('DemoController', function() {
10946               this.label = "This binding is brought you by // interpolation symbols.";
10947           });
10948         </script>
10949         <div ng-app="App" ng-controller="DemoController as demo">
10950             //demo.label//
10951         </div>
10952         </file>
10953         <file name="protractor.js" type="protractor">
10954           it('should interpolate binding with custom symbols', function() {
10955             expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
10956           });
10957         </file>
10958         </example>
10959          */
10960         function $InterpolateProvider() {
10961           var startSymbol = '{{';
10962           var endSymbol = '}}';
10963
10964           /**
10965            * @ngdoc method
10966            * @name $interpolateProvider#startSymbol
10967            * @description
10968            * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
10969            *
10970            * @param {string=} value new value to set the starting symbol to.
10971            * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
10972            */
10973           this.startSymbol = function(value) {
10974             if (value) {
10975               startSymbol = value;
10976               return this;
10977             } else {
10978               return startSymbol;
10979             }
10980           };
10981
10982           /**
10983            * @ngdoc method
10984            * @name $interpolateProvider#endSymbol
10985            * @description
10986            * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
10987            *
10988            * @param {string=} value new value to set the ending symbol to.
10989            * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
10990            */
10991           this.endSymbol = function(value) {
10992             if (value) {
10993               endSymbol = value;
10994               return this;
10995             } else {
10996               return endSymbol;
10997             }
10998           };
10999
11000
11001           this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
11002             var startSymbolLength = startSymbol.length,
11003                 endSymbolLength = endSymbol.length,
11004                 escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),
11005                 escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');
11006
11007             function escape(ch) {
11008               return '\\\\\\' + ch;
11009             }
11010
11011             function unescapeText(text) {
11012               return text.replace(escapedStartRegexp, startSymbol).
11013                 replace(escapedEndRegexp, endSymbol);
11014             }
11015
11016             function stringify(value) {
11017               if (value == null) { // null || undefined
11018                 return '';
11019               }
11020               switch (typeof value) {
11021                 case 'string':
11022                   break;
11023                 case 'number':
11024                   value = '' + value;
11025                   break;
11026                 default:
11027                   value = toJson(value);
11028               }
11029
11030               return value;
11031             }
11032
11033             /**
11034              * @ngdoc service
11035              * @name $interpolate
11036              * @kind function
11037              *
11038              * @requires $parse
11039              * @requires $sce
11040              *
11041              * @description
11042              *
11043              * Compiles a string with markup into an interpolation function. This service is used by the
11044              * HTML {@link ng.$compile $compile} service for data binding. See
11045              * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
11046              * interpolation markup.
11047              *
11048              *
11049              * ```js
11050              *   var $interpolate = ...; // injected
11051              *   var exp = $interpolate('Hello {{name | uppercase}}!');
11052              *   expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!');
11053              * ```
11054              *
11055              * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
11056              * `true`, the interpolation function will return `undefined` unless all embedded expressions
11057              * evaluate to a value other than `undefined`.
11058              *
11059              * ```js
11060              *   var $interpolate = ...; // injected
11061              *   var context = {greeting: 'Hello', name: undefined };
11062              *
11063              *   // default "forgiving" mode
11064              *   var exp = $interpolate('{{greeting}} {{name}}!');
11065              *   expect(exp(context)).toEqual('Hello !');
11066              *
11067              *   // "allOrNothing" mode
11068              *   exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
11069              *   expect(exp(context)).toBeUndefined();
11070              *   context.name = 'Angular';
11071              *   expect(exp(context)).toEqual('Hello Angular!');
11072              * ```
11073              *
11074              * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
11075              *
11076              * ####Escaped Interpolation
11077              * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
11078              * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
11079              * It will be rendered as a regular start/end marker, and will not be interpreted as an expression
11080              * or binding.
11081              *
11082              * This enables web-servers to prevent script injection attacks and defacing attacks, to some
11083              * degree, while also enabling code examples to work without relying on the
11084              * {@link ng.directive:ngNonBindable ngNonBindable} directive.
11085              *
11086              * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
11087              * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
11088              * interpolation start/end markers with their escaped counterparts.**
11089              *
11090              * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
11091              * output when the $interpolate service processes the text. So, for HTML elements interpolated
11092              * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
11093              * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
11094              * this is typically useful only when user-data is used in rendering a template from the server, or
11095              * when otherwise untrusted data is used by a directive.
11096              *
11097              * <example>
11098              *  <file name="index.html">
11099              *    <div ng-init="username='A user'">
11100              *      <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
11101              *        </p>
11102              *      <p><strong>{{username}}</strong> attempts to inject code which will deface the
11103              *        application, but fails to accomplish their task, because the server has correctly
11104              *        escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
11105              *        characters.</p>
11106              *      <p>Instead, the result of the attempted script injection is visible, and can be removed
11107              *        from the database by an administrator.</p>
11108              *    </div>
11109              *  </file>
11110              * </example>
11111              *
11112              * @param {string} text The text with markup to interpolate.
11113              * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
11114              *    embedded expression in order to return an interpolation function. Strings with no
11115              *    embedded expression will return null for the interpolation function.
11116              * @param {string=} trustedContext when provided, the returned function passes the interpolated
11117              *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
11118              *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that
11119              *    provides Strict Contextual Escaping for details.
11120              * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
11121              *    unless all embedded expressions evaluate to a value other than `undefined`.
11122              * @returns {function(context)} an interpolation function which is used to compute the
11123              *    interpolated string. The function has these parameters:
11124              *
11125              * - `context`: evaluation context for all expressions embedded in the interpolated text
11126              */
11127             function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
11128               allOrNothing = !!allOrNothing;
11129               var startIndex,
11130                   endIndex,
11131                   index = 0,
11132                   expressions = [],
11133                   parseFns = [],
11134                   textLength = text.length,
11135                   exp,
11136                   concat = [],
11137                   expressionPositions = [];
11138
11139               while (index < textLength) {
11140                 if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
11141                      ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
11142                   if (index !== startIndex) {
11143                     concat.push(unescapeText(text.substring(index, startIndex)));
11144                   }
11145                   exp = text.substring(startIndex + startSymbolLength, endIndex);
11146                   expressions.push(exp);
11147                   parseFns.push($parse(exp, parseStringifyInterceptor));
11148                   index = endIndex + endSymbolLength;
11149                   expressionPositions.push(concat.length);
11150                   concat.push('');
11151                 } else {
11152                   // we did not find an interpolation, so we have to add the remainder to the separators array
11153                   if (index !== textLength) {
11154                     concat.push(unescapeText(text.substring(index)));
11155                   }
11156                   break;
11157                 }
11158               }
11159
11160               // Concatenating expressions makes it hard to reason about whether some combination of
11161               // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a
11162               // single expression be used for iframe[src], object[src], etc., we ensure that the value
11163               // that's used is assigned or constructed by some JS code somewhere that is more testable or
11164               // make it obvious that you bound the value to some user controlled value.  This helps reduce
11165               // the load when auditing for XSS issues.
11166               if (trustedContext && concat.length > 1) {
11167                   $interpolateMinErr.throwNoconcat(text);
11168               }
11169
11170               if (!mustHaveExpression || expressions.length) {
11171                 var compute = function(values) {
11172                   for (var i = 0, ii = expressions.length; i < ii; i++) {
11173                     if (allOrNothing && isUndefined(values[i])) return;
11174                     concat[expressionPositions[i]] = values[i];
11175                   }
11176                   return concat.join('');
11177                 };
11178
11179                 var getValue = function(value) {
11180                   return trustedContext ?
11181                     $sce.getTrusted(trustedContext, value) :
11182                     $sce.valueOf(value);
11183                 };
11184
11185                 return extend(function interpolationFn(context) {
11186                     var i = 0;
11187                     var ii = expressions.length;
11188                     var values = new Array(ii);
11189
11190                     try {
11191                       for (; i < ii; i++) {
11192                         values[i] = parseFns[i](context);
11193                       }
11194
11195                       return compute(values);
11196                     } catch (err) {
11197                       $exceptionHandler($interpolateMinErr.interr(text, err));
11198                     }
11199
11200                   }, {
11201                   // all of these properties are undocumented for now
11202                   exp: text, //just for compatibility with regular watchers created via $watch
11203                   expressions: expressions,
11204                   $$watchDelegate: function(scope, listener) {
11205                     var lastValue;
11206                     return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
11207                       var currValue = compute(values);
11208                       if (isFunction(listener)) {
11209                         listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
11210                       }
11211                       lastValue = currValue;
11212                     });
11213                   }
11214                 });
11215               }
11216
11217               function parseStringifyInterceptor(value) {
11218                 try {
11219                   value = getValue(value);
11220                   return allOrNothing && !isDefined(value) ? value : stringify(value);
11221                 } catch (err) {
11222                   $exceptionHandler($interpolateMinErr.interr(text, err));
11223                 }
11224               }
11225             }
11226
11227
11228             /**
11229              * @ngdoc method
11230              * @name $interpolate#startSymbol
11231              * @description
11232              * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
11233              *
11234              * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
11235              * the symbol.
11236              *
11237              * @returns {string} start symbol.
11238              */
11239             $interpolate.startSymbol = function() {
11240               return startSymbol;
11241             };
11242
11243
11244             /**
11245              * @ngdoc method
11246              * @name $interpolate#endSymbol
11247              * @description
11248              * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
11249              *
11250              * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
11251              * the symbol.
11252              *
11253              * @returns {string} end symbol.
11254              */
11255             $interpolate.endSymbol = function() {
11256               return endSymbol;
11257             };
11258
11259             return $interpolate;
11260           }];
11261         }
11262
11263         function $IntervalProvider() {
11264           this.$get = ['$rootScope', '$window', '$q', '$$q',
11265                function($rootScope,   $window,   $q,   $$q) {
11266             var intervals = {};
11267
11268
11269              /**
11270               * @ngdoc service
11271               * @name $interval
11272               *
11273               * @description
11274               * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
11275               * milliseconds.
11276               *
11277               * The return value of registering an interval function is a promise. This promise will be
11278               * notified upon each tick of the interval, and will be resolved after `count` iterations, or
11279               * run indefinitely if `count` is not defined. The value of the notification will be the
11280               * number of iterations that have run.
11281               * To cancel an interval, call `$interval.cancel(promise)`.
11282               *
11283               * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
11284               * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
11285               * time.
11286               *
11287               * <div class="alert alert-warning">
11288               * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
11289               * with them.  In particular they are not automatically destroyed when a controller's scope or a
11290               * directive's element are destroyed.
11291               * You should take this into consideration and make sure to always cancel the interval at the
11292               * appropriate moment.  See the example below for more details on how and when to do this.
11293               * </div>
11294               *
11295               * @param {function()} fn A function that should be called repeatedly.
11296               * @param {number} delay Number of milliseconds between each function call.
11297               * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
11298               *   indefinitely.
11299               * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
11300               *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
11301               * @param {...*=} Pass additional parameters to the executed function.
11302               * @returns {promise} A promise which will be notified on each iteration.
11303               *
11304               * @example
11305               * <example module="intervalExample">
11306               * <file name="index.html">
11307               *   <script>
11308               *     angular.module('intervalExample', [])
11309               *       .controller('ExampleController', ['$scope', '$interval',
11310               *         function($scope, $interval) {
11311               *           $scope.format = 'M/d/yy h:mm:ss a';
11312               *           $scope.blood_1 = 100;
11313               *           $scope.blood_2 = 120;
11314               *
11315               *           var stop;
11316               *           $scope.fight = function() {
11317               *             // Don't start a new fight if we are already fighting
11318               *             if ( angular.isDefined(stop) ) return;
11319               *
11320               *             stop = $interval(function() {
11321               *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
11322               *                 $scope.blood_1 = $scope.blood_1 - 3;
11323               *                 $scope.blood_2 = $scope.blood_2 - 4;
11324               *               } else {
11325               *                 $scope.stopFight();
11326               *               }
11327               *             }, 100);
11328               *           };
11329               *
11330               *           $scope.stopFight = function() {
11331               *             if (angular.isDefined(stop)) {
11332               *               $interval.cancel(stop);
11333               *               stop = undefined;
11334               *             }
11335               *           };
11336               *
11337               *           $scope.resetFight = function() {
11338               *             $scope.blood_1 = 100;
11339               *             $scope.blood_2 = 120;
11340               *           };
11341               *
11342               *           $scope.$on('$destroy', function() {
11343               *             // Make sure that the interval is destroyed too
11344               *             $scope.stopFight();
11345               *           });
11346               *         }])
11347               *       // Register the 'myCurrentTime' directive factory method.
11348               *       // We inject $interval and dateFilter service since the factory method is DI.
11349               *       .directive('myCurrentTime', ['$interval', 'dateFilter',
11350               *         function($interval, dateFilter) {
11351               *           // return the directive link function. (compile function not needed)
11352               *           return function(scope, element, attrs) {
11353               *             var format,  // date format
11354               *                 stopTime; // so that we can cancel the time updates
11355               *
11356               *             // used to update the UI
11357               *             function updateTime() {
11358               *               element.text(dateFilter(new Date(), format));
11359               *             }
11360               *
11361               *             // watch the expression, and update the UI on change.
11362               *             scope.$watch(attrs.myCurrentTime, function(value) {
11363               *               format = value;
11364               *               updateTime();
11365               *             });
11366               *
11367               *             stopTime = $interval(updateTime, 1000);
11368               *
11369               *             // listen on DOM destroy (removal) event, and cancel the next UI update
11370               *             // to prevent updating time after the DOM element was removed.
11371               *             element.on('$destroy', function() {
11372               *               $interval.cancel(stopTime);
11373               *             });
11374               *           }
11375               *         }]);
11376               *   </script>
11377               *
11378               *   <div>
11379               *     <div ng-controller="ExampleController">
11380               *       <label>Date format: <input ng-model="format"></label> <hr/>
11381               *       Current time is: <span my-current-time="format"></span>
11382               *       <hr/>
11383               *       Blood 1 : <font color='red'>{{blood_1}}</font>
11384               *       Blood 2 : <font color='red'>{{blood_2}}</font>
11385               *       <button type="button" data-ng-click="fight()">Fight</button>
11386               *       <button type="button" data-ng-click="stopFight()">StopFight</button>
11387               *       <button type="button" data-ng-click="resetFight()">resetFight</button>
11388               *     </div>
11389               *   </div>
11390               *
11391               * </file>
11392               * </example>
11393               */
11394             function interval(fn, delay, count, invokeApply) {
11395               var hasParams = arguments.length > 4,
11396                   args = hasParams ? sliceArgs(arguments, 4) : [],
11397                   setInterval = $window.setInterval,
11398                   clearInterval = $window.clearInterval,
11399                   iteration = 0,
11400                   skipApply = (isDefined(invokeApply) && !invokeApply),
11401                   deferred = (skipApply ? $$q : $q).defer(),
11402                   promise = deferred.promise;
11403
11404               count = isDefined(count) ? count : 0;
11405
11406               promise.then(null, null, (!hasParams) ? fn : function() {
11407                 fn.apply(null, args);
11408               });
11409
11410               promise.$$intervalId = setInterval(function tick() {
11411                 deferred.notify(iteration++);
11412
11413                 if (count > 0 && iteration >= count) {
11414                   deferred.resolve(iteration);
11415                   clearInterval(promise.$$intervalId);
11416                   delete intervals[promise.$$intervalId];
11417                 }
11418
11419                 if (!skipApply) $rootScope.$apply();
11420
11421               }, delay);
11422
11423               intervals[promise.$$intervalId] = deferred;
11424
11425               return promise;
11426             }
11427
11428
11429              /**
11430               * @ngdoc method
11431               * @name $interval#cancel
11432               *
11433               * @description
11434               * Cancels a task associated with the `promise`.
11435               *
11436               * @param {Promise=} promise returned by the `$interval` function.
11437               * @returns {boolean} Returns `true` if the task was successfully canceled.
11438               */
11439             interval.cancel = function(promise) {
11440               if (promise && promise.$$intervalId in intervals) {
11441                 intervals[promise.$$intervalId].reject('canceled');
11442                 $window.clearInterval(promise.$$intervalId);
11443                 delete intervals[promise.$$intervalId];
11444                 return true;
11445               }
11446               return false;
11447             };
11448
11449             return interval;
11450           }];
11451         }
11452
11453         /**
11454          * @ngdoc service
11455          * @name $locale
11456          *
11457          * @description
11458          * $locale service provides localization rules for various Angular components. As of right now the
11459          * only public api is:
11460          *
11461          * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
11462          */
11463
11464         var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
11465             DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
11466         var $locationMinErr = minErr('$location');
11467
11468
11469         /**
11470          * Encode path using encodeUriSegment, ignoring forward slashes
11471          *
11472          * @param {string} path Path to encode
11473          * @returns {string}
11474          */
11475         function encodePath(path) {
11476           var segments = path.split('/'),
11477               i = segments.length;
11478
11479           while (i--) {
11480             segments[i] = encodeUriSegment(segments[i]);
11481           }
11482
11483           return segments.join('/');
11484         }
11485
11486         function parseAbsoluteUrl(absoluteUrl, locationObj) {
11487           var parsedUrl = urlResolve(absoluteUrl);
11488
11489           locationObj.$$protocol = parsedUrl.protocol;
11490           locationObj.$$host = parsedUrl.hostname;
11491           locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
11492         }
11493
11494
11495         function parseAppUrl(relativeUrl, locationObj) {
11496           var prefixed = (relativeUrl.charAt(0) !== '/');
11497           if (prefixed) {
11498             relativeUrl = '/' + relativeUrl;
11499           }
11500           var match = urlResolve(relativeUrl);
11501           locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
11502               match.pathname.substring(1) : match.pathname);
11503           locationObj.$$search = parseKeyValue(match.search);
11504           locationObj.$$hash = decodeURIComponent(match.hash);
11505
11506           // make sure path starts with '/';
11507           if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
11508             locationObj.$$path = '/' + locationObj.$$path;
11509           }
11510         }
11511
11512
11513         /**
11514          *
11515          * @param {string} begin
11516          * @param {string} whole
11517          * @returns {string} returns text from whole after begin or undefined if it does not begin with
11518          *                   expected string.
11519          */
11520         function beginsWith(begin, whole) {
11521           if (whole.indexOf(begin) === 0) {
11522             return whole.substr(begin.length);
11523           }
11524         }
11525
11526
11527         function stripHash(url) {
11528           var index = url.indexOf('#');
11529           return index == -1 ? url : url.substr(0, index);
11530         }
11531
11532         function trimEmptyHash(url) {
11533           return url.replace(/(#.+)|#$/, '$1');
11534         }
11535
11536
11537         function stripFile(url) {
11538           return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
11539         }
11540
11541         /* return the server only (scheme://host:port) */
11542         function serverBase(url) {
11543           return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
11544         }
11545
11546
11547         /**
11548          * LocationHtml5Url represents an url
11549          * This object is exposed as $location service when HTML5 mode is enabled and supported
11550          *
11551          * @constructor
11552          * @param {string} appBase application base URL
11553          * @param {string} appBaseNoFile application base URL stripped of any filename
11554          * @param {string} basePrefix url path prefix
11555          */
11556         function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
11557           this.$$html5 = true;
11558           basePrefix = basePrefix || '';
11559           parseAbsoluteUrl(appBase, this);
11560
11561
11562           /**
11563            * Parse given html5 (regular) url string into properties
11564            * @param {string} url HTML5 url
11565            * @private
11566            */
11567           this.$$parse = function(url) {
11568             var pathUrl = beginsWith(appBaseNoFile, url);
11569             if (!isString(pathUrl)) {
11570               throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
11571                   appBaseNoFile);
11572             }
11573
11574             parseAppUrl(pathUrl, this);
11575
11576             if (!this.$$path) {
11577               this.$$path = '/';
11578             }
11579
11580             this.$$compose();
11581           };
11582
11583           /**
11584            * Compose url and update `absUrl` property
11585            * @private
11586            */
11587           this.$$compose = function() {
11588             var search = toKeyValue(this.$$search),
11589                 hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
11590
11591             this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
11592             this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
11593           };
11594
11595           this.$$parseLinkUrl = function(url, relHref) {
11596             if (relHref && relHref[0] === '#') {
11597               // special case for links to hash fragments:
11598               // keep the old url and only replace the hash fragment
11599               this.hash(relHref.slice(1));
11600               return true;
11601             }
11602             var appUrl, prevAppUrl;
11603             var rewrittenUrl;
11604
11605             if (isDefined(appUrl = beginsWith(appBase, url))) {
11606               prevAppUrl = appUrl;
11607               if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
11608                 rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
11609               } else {
11610                 rewrittenUrl = appBase + prevAppUrl;
11611               }
11612             } else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
11613               rewrittenUrl = appBaseNoFile + appUrl;
11614             } else if (appBaseNoFile == url + '/') {
11615               rewrittenUrl = appBaseNoFile;
11616             }
11617             if (rewrittenUrl) {
11618               this.$$parse(rewrittenUrl);
11619             }
11620             return !!rewrittenUrl;
11621           };
11622         }
11623
11624
11625         /**
11626          * LocationHashbangUrl represents url
11627          * This object is exposed as $location service when developer doesn't opt into html5 mode.
11628          * It also serves as the base class for html5 mode fallback on legacy browsers.
11629          *
11630          * @constructor
11631          * @param {string} appBase application base URL
11632          * @param {string} appBaseNoFile application base URL stripped of any filename
11633          * @param {string} hashPrefix hashbang prefix
11634          */
11635         function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
11636
11637           parseAbsoluteUrl(appBase, this);
11638
11639
11640           /**
11641            * Parse given hashbang url into properties
11642            * @param {string} url Hashbang url
11643            * @private
11644            */
11645           this.$$parse = function(url) {
11646             var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
11647             var withoutHashUrl;
11648
11649             if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
11650
11651               // The rest of the url starts with a hash so we have
11652               // got either a hashbang path or a plain hash fragment
11653               withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
11654               if (isUndefined(withoutHashUrl)) {
11655                 // There was no hashbang prefix so we just have a hash fragment
11656                 withoutHashUrl = withoutBaseUrl;
11657               }
11658
11659             } else {
11660               // There was no hashbang path nor hash fragment:
11661               // If we are in HTML5 mode we use what is left as the path;
11662               // Otherwise we ignore what is left
11663               if (this.$$html5) {
11664                 withoutHashUrl = withoutBaseUrl;
11665               } else {
11666                 withoutHashUrl = '';
11667                 if (isUndefined(withoutBaseUrl)) {
11668                   appBase = url;
11669                   this.replace();
11670                 }
11671               }
11672             }
11673
11674             parseAppUrl(withoutHashUrl, this);
11675
11676             this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
11677
11678             this.$$compose();
11679
11680             /*
11681              * In Windows, on an anchor node on documents loaded from
11682              * the filesystem, the browser will return a pathname
11683              * prefixed with the drive name ('/C:/path') when a
11684              * pathname without a drive is set:
11685              *  * a.setAttribute('href', '/foo')
11686              *   * a.pathname === '/C:/foo' //true
11687              *
11688              * Inside of Angular, we're always using pathnames that
11689              * do not include drive names for routing.
11690              */
11691             function removeWindowsDriveName(path, url, base) {
11692               /*
11693               Matches paths for file protocol on windows,
11694               such as /C:/foo/bar, and captures only /foo/bar.
11695               */
11696               var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
11697
11698               var firstPathSegmentMatch;
11699
11700               //Get the relative path from the input URL.
11701               if (url.indexOf(base) === 0) {
11702                 url = url.replace(base, '');
11703               }
11704
11705               // The input URL intentionally contains a first path segment that ends with a colon.
11706               if (windowsFilePathExp.exec(url)) {
11707                 return path;
11708               }
11709
11710               firstPathSegmentMatch = windowsFilePathExp.exec(path);
11711               return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
11712             }
11713           };
11714
11715           /**
11716            * Compose hashbang url and update `absUrl` property
11717            * @private
11718            */
11719           this.$$compose = function() {
11720             var search = toKeyValue(this.$$search),
11721                 hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
11722
11723             this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
11724             this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
11725           };
11726
11727           this.$$parseLinkUrl = function(url, relHref) {
11728             if (stripHash(appBase) == stripHash(url)) {
11729               this.$$parse(url);
11730               return true;
11731             }
11732             return false;
11733           };
11734         }
11735
11736
11737         /**
11738          * LocationHashbangUrl represents url
11739          * This object is exposed as $location service when html5 history api is enabled but the browser
11740          * does not support it.
11741          *
11742          * @constructor
11743          * @param {string} appBase application base URL
11744          * @param {string} appBaseNoFile application base URL stripped of any filename
11745          * @param {string} hashPrefix hashbang prefix
11746          */
11747         function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
11748           this.$$html5 = true;
11749           LocationHashbangUrl.apply(this, arguments);
11750
11751           this.$$parseLinkUrl = function(url, relHref) {
11752             if (relHref && relHref[0] === '#') {
11753               // special case for links to hash fragments:
11754               // keep the old url and only replace the hash fragment
11755               this.hash(relHref.slice(1));
11756               return true;
11757             }
11758
11759             var rewrittenUrl;
11760             var appUrl;
11761
11762             if (appBase == stripHash(url)) {
11763               rewrittenUrl = url;
11764             } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
11765               rewrittenUrl = appBase + hashPrefix + appUrl;
11766             } else if (appBaseNoFile === url + '/') {
11767               rewrittenUrl = appBaseNoFile;
11768             }
11769             if (rewrittenUrl) {
11770               this.$$parse(rewrittenUrl);
11771             }
11772             return !!rewrittenUrl;
11773           };
11774
11775           this.$$compose = function() {
11776             var search = toKeyValue(this.$$search),
11777                 hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
11778
11779             this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
11780             // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'
11781             this.$$absUrl = appBase + hashPrefix + this.$$url;
11782           };
11783
11784         }
11785
11786
11787         var locationPrototype = {
11788
11789           /**
11790            * Are we in html5 mode?
11791            * @private
11792            */
11793           $$html5: false,
11794
11795           /**
11796            * Has any change been replacing?
11797            * @private
11798            */
11799           $$replace: false,
11800
11801           /**
11802            * @ngdoc method
11803            * @name $location#absUrl
11804            *
11805            * @description
11806            * This method is getter only.
11807            *
11808            * Return full url representation with all segments encoded according to rules specified in
11809            * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
11810            *
11811            *
11812            * ```js
11813            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11814            * var absUrl = $location.absUrl();
11815            * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
11816            * ```
11817            *
11818            * @return {string} full url
11819            */
11820           absUrl: locationGetter('$$absUrl'),
11821
11822           /**
11823            * @ngdoc method
11824            * @name $location#url
11825            *
11826            * @description
11827            * This method is getter / setter.
11828            *
11829            * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
11830            *
11831            * Change path, search and hash, when called with parameter and return `$location`.
11832            *
11833            *
11834            * ```js
11835            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11836            * var url = $location.url();
11837            * // => "/some/path?foo=bar&baz=xoxo"
11838            * ```
11839            *
11840            * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
11841            * @return {string} url
11842            */
11843           url: function(url) {
11844             if (isUndefined(url)) {
11845               return this.$$url;
11846             }
11847
11848             var match = PATH_MATCH.exec(url);
11849             if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
11850             if (match[2] || match[1] || url === '') this.search(match[3] || '');
11851             this.hash(match[5] || '');
11852
11853             return this;
11854           },
11855
11856           /**
11857            * @ngdoc method
11858            * @name $location#protocol
11859            *
11860            * @description
11861            * This method is getter only.
11862            *
11863            * Return protocol of current url.
11864            *
11865            *
11866            * ```js
11867            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11868            * var protocol = $location.protocol();
11869            * // => "http"
11870            * ```
11871            *
11872            * @return {string} protocol of current url
11873            */
11874           protocol: locationGetter('$$protocol'),
11875
11876           /**
11877            * @ngdoc method
11878            * @name $location#host
11879            *
11880            * @description
11881            * This method is getter only.
11882            *
11883            * Return host of current url.
11884            *
11885            * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
11886            *
11887            *
11888            * ```js
11889            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11890            * var host = $location.host();
11891            * // => "example.com"
11892            *
11893            * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
11894            * host = $location.host();
11895            * // => "example.com"
11896            * host = location.host;
11897            * // => "example.com:8080"
11898            * ```
11899            *
11900            * @return {string} host of current url.
11901            */
11902           host: locationGetter('$$host'),
11903
11904           /**
11905            * @ngdoc method
11906            * @name $location#port
11907            *
11908            * @description
11909            * This method is getter only.
11910            *
11911            * Return port of current url.
11912            *
11913            *
11914            * ```js
11915            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11916            * var port = $location.port();
11917            * // => 80
11918            * ```
11919            *
11920            * @return {Number} port
11921            */
11922           port: locationGetter('$$port'),
11923
11924           /**
11925            * @ngdoc method
11926            * @name $location#path
11927            *
11928            * @description
11929            * This method is getter / setter.
11930            *
11931            * Return path of current url when called without any parameter.
11932            *
11933            * Change path when called with parameter and return `$location`.
11934            *
11935            * Note: Path should always begin with forward slash (/), this method will add the forward slash
11936            * if it is missing.
11937            *
11938            *
11939            * ```js
11940            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11941            * var path = $location.path();
11942            * // => "/some/path"
11943            * ```
11944            *
11945            * @param {(string|number)=} path New path
11946            * @return {string} path
11947            */
11948           path: locationGetterSetter('$$path', function(path) {
11949             path = path !== null ? path.toString() : '';
11950             return path.charAt(0) == '/' ? path : '/' + path;
11951           }),
11952
11953           /**
11954            * @ngdoc method
11955            * @name $location#search
11956            *
11957            * @description
11958            * This method is getter / setter.
11959            *
11960            * Return search part (as object) of current url when called without any parameter.
11961            *
11962            * Change search part when called with parameter and return `$location`.
11963            *
11964            *
11965            * ```js
11966            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11967            * var searchObject = $location.search();
11968            * // => {foo: 'bar', baz: 'xoxo'}
11969            *
11970            * // set foo to 'yipee'
11971            * $location.search('foo', 'yipee');
11972            * // $location.search() => {foo: 'yipee', baz: 'xoxo'}
11973            * ```
11974            *
11975            * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
11976            * hash object.
11977            *
11978            * When called with a single argument the method acts as a setter, setting the `search` component
11979            * of `$location` to the specified value.
11980            *
11981            * If the argument is a hash object containing an array of values, these values will be encoded
11982            * as duplicate search parameters in the url.
11983            *
11984            * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
11985            * will override only a single search property.
11986            *
11987            * If `paramValue` is an array, it will override the property of the `search` component of
11988            * `$location` specified via the first argument.
11989            *
11990            * If `paramValue` is `null`, the property specified via the first argument will be deleted.
11991            *
11992            * If `paramValue` is `true`, the property specified via the first argument will be added with no
11993            * value nor trailing equal sign.
11994            *
11995            * @return {Object} If called with no arguments returns the parsed `search` object. If called with
11996            * one or more arguments returns `$location` object itself.
11997            */
11998           search: function(search, paramValue) {
11999             switch (arguments.length) {
12000               case 0:
12001                 return this.$$search;
12002               case 1:
12003                 if (isString(search) || isNumber(search)) {
12004                   search = search.toString();
12005                   this.$$search = parseKeyValue(search);
12006                 } else if (isObject(search)) {
12007                   search = copy(search, {});
12008                   // remove object undefined or null properties
12009                   forEach(search, function(value, key) {
12010                     if (value == null) delete search[key];
12011                   });
12012
12013                   this.$$search = search;
12014                 } else {
12015                   throw $locationMinErr('isrcharg',
12016                       'The first argument of the `$location#search()` call must be a string or an object.');
12017                 }
12018                 break;
12019               default:
12020                 if (isUndefined(paramValue) || paramValue === null) {
12021                   delete this.$$search[search];
12022                 } else {
12023                   this.$$search[search] = paramValue;
12024                 }
12025             }
12026
12027             this.$$compose();
12028             return this;
12029           },
12030
12031           /**
12032            * @ngdoc method
12033            * @name $location#hash
12034            *
12035            * @description
12036            * This method is getter / setter.
12037            *
12038            * Returns the hash fragment when called without any parameters.
12039            *
12040            * Changes the hash fragment when called with a parameter and returns `$location`.
12041            *
12042            *
12043            * ```js
12044            * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
12045            * var hash = $location.hash();
12046            * // => "hashValue"
12047            * ```
12048            *
12049            * @param {(string|number)=} hash New hash fragment
12050            * @return {string} hash
12051            */
12052           hash: locationGetterSetter('$$hash', function(hash) {
12053             return hash !== null ? hash.toString() : '';
12054           }),
12055
12056           /**
12057            * @ngdoc method
12058            * @name $location#replace
12059            *
12060            * @description
12061            * If called, all changes to $location during the current `$digest` will replace the current history
12062            * record, instead of adding a new one.
12063            */
12064           replace: function() {
12065             this.$$replace = true;
12066             return this;
12067           }
12068         };
12069
12070         forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
12071           Location.prototype = Object.create(locationPrototype);
12072
12073           /**
12074            * @ngdoc method
12075            * @name $location#state
12076            *
12077            * @description
12078            * This method is getter / setter.
12079            *
12080            * Return the history state object when called without any parameter.
12081            *
12082            * Change the history state object when called with one parameter and return `$location`.
12083            * The state object is later passed to `pushState` or `replaceState`.
12084            *
12085            * NOTE: This method is supported only in HTML5 mode and only in browsers supporting
12086            * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support
12087            * older browsers (like IE9 or Android < 4.0), don't use this method.
12088            *
12089            * @param {object=} state State object for pushState or replaceState
12090            * @return {object} state
12091            */
12092           Location.prototype.state = function(state) {
12093             if (!arguments.length) {
12094               return this.$$state;
12095             }
12096
12097             if (Location !== LocationHtml5Url || !this.$$html5) {
12098               throw $locationMinErr('nostate', 'History API state support is available only ' +
12099                 'in HTML5 mode and only in browsers supporting HTML5 History API');
12100             }
12101             // The user might modify `stateObject` after invoking `$location.state(stateObject)`
12102             // but we're changing the $$state reference to $browser.state() during the $digest
12103             // so the modification window is narrow.
12104             this.$$state = isUndefined(state) ? null : state;
12105
12106             return this;
12107           };
12108         });
12109
12110
12111         function locationGetter(property) {
12112           return function() {
12113             return this[property];
12114           };
12115         }
12116
12117
12118         function locationGetterSetter(property, preprocess) {
12119           return function(value) {
12120             if (isUndefined(value)) {
12121               return this[property];
12122             }
12123
12124             this[property] = preprocess(value);
12125             this.$$compose();
12126
12127             return this;
12128           };
12129         }
12130
12131
12132         /**
12133          * @ngdoc service
12134          * @name $location
12135          *
12136          * @requires $rootElement
12137          *
12138          * @description
12139          * The $location service parses the URL in the browser address bar (based on the
12140          * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
12141          * available to your application. Changes to the URL in the address bar are reflected into
12142          * $location service and changes to $location are reflected into the browser address bar.
12143          *
12144          * **The $location service:**
12145          *
12146          * - Exposes the current URL in the browser address bar, so you can
12147          *   - Watch and observe the URL.
12148          *   - Change the URL.
12149          * - Synchronizes the URL with the browser when the user
12150          *   - Changes the address bar.
12151          *   - Clicks the back or forward button (or clicks a History link).
12152          *   - Clicks on a link.
12153          * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
12154          *
12155          * For more information see {@link guide/$location Developer Guide: Using $location}
12156          */
12157
12158         /**
12159          * @ngdoc provider
12160          * @name $locationProvider
12161          * @description
12162          * Use the `$locationProvider` to configure how the application deep linking paths are stored.
12163          */
12164         function $LocationProvider() {
12165           var hashPrefix = '',
12166               html5Mode = {
12167                 enabled: false,
12168                 requireBase: true,
12169                 rewriteLinks: true
12170               };
12171
12172           /**
12173            * @ngdoc method
12174            * @name $locationProvider#hashPrefix
12175            * @description
12176            * @param {string=} prefix Prefix for hash part (containing path and search)
12177            * @returns {*} current value if used as getter or itself (chaining) if used as setter
12178            */
12179           this.hashPrefix = function(prefix) {
12180             if (isDefined(prefix)) {
12181               hashPrefix = prefix;
12182               return this;
12183             } else {
12184               return hashPrefix;
12185             }
12186           };
12187
12188           /**
12189            * @ngdoc method
12190            * @name $locationProvider#html5Mode
12191            * @description
12192            * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
12193            *   If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
12194            *   properties:
12195            *   - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
12196            *     change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
12197            *     support `pushState`.
12198            *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
12199            *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
12200            *     true, and a base tag is not present, an error will be thrown when `$location` is injected.
12201            *     See the {@link guide/$location $location guide for more information}
12202            *   - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
12203            *     enables/disables url rewriting for relative links.
12204            *
12205            * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
12206            */
12207           this.html5Mode = function(mode) {
12208             if (isBoolean(mode)) {
12209               html5Mode.enabled = mode;
12210               return this;
12211             } else if (isObject(mode)) {
12212
12213               if (isBoolean(mode.enabled)) {
12214                 html5Mode.enabled = mode.enabled;
12215               }
12216
12217               if (isBoolean(mode.requireBase)) {
12218                 html5Mode.requireBase = mode.requireBase;
12219               }
12220
12221               if (isBoolean(mode.rewriteLinks)) {
12222                 html5Mode.rewriteLinks = mode.rewriteLinks;
12223               }
12224
12225               return this;
12226             } else {
12227               return html5Mode;
12228             }
12229           };
12230
12231           /**
12232            * @ngdoc event
12233            * @name $location#$locationChangeStart
12234            * @eventType broadcast on root scope
12235            * @description
12236            * Broadcasted before a URL will change.
12237            *
12238            * This change can be prevented by calling
12239            * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
12240            * details about event object. Upon successful change
12241            * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
12242            *
12243            * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
12244            * the browser supports the HTML5 History API.
12245            *
12246            * @param {Object} angularEvent Synthetic event object.
12247            * @param {string} newUrl New URL
12248            * @param {string=} oldUrl URL that was before it was changed.
12249            * @param {string=} newState New history state object
12250            * @param {string=} oldState History state object that was before it was changed.
12251            */
12252
12253           /**
12254            * @ngdoc event
12255            * @name $location#$locationChangeSuccess
12256            * @eventType broadcast on root scope
12257            * @description
12258            * Broadcasted after a URL was changed.
12259            *
12260            * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
12261            * the browser supports the HTML5 History API.
12262            *
12263            * @param {Object} angularEvent Synthetic event object.
12264            * @param {string} newUrl New URL
12265            * @param {string=} oldUrl URL that was before it was changed.
12266            * @param {string=} newState New history state object
12267            * @param {string=} oldState History state object that was before it was changed.
12268            */
12269
12270           this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
12271               function($rootScope, $browser, $sniffer, $rootElement, $window) {
12272             var $location,
12273                 LocationMode,
12274                 baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
12275                 initialUrl = $browser.url(),
12276                 appBase;
12277
12278             if (html5Mode.enabled) {
12279               if (!baseHref && html5Mode.requireBase) {
12280                 throw $locationMinErr('nobase',
12281                   "$location in HTML5 mode requires a <base> tag to be present!");
12282               }
12283               appBase = serverBase(initialUrl) + (baseHref || '/');
12284               LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
12285             } else {
12286               appBase = stripHash(initialUrl);
12287               LocationMode = LocationHashbangUrl;
12288             }
12289             var appBaseNoFile = stripFile(appBase);
12290
12291             $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
12292             $location.$$parseLinkUrl(initialUrl, initialUrl);
12293
12294             $location.$$state = $browser.state();
12295
12296             var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
12297
12298             function setBrowserUrlWithFallback(url, replace, state) {
12299               var oldUrl = $location.url();
12300               var oldState = $location.$$state;
12301               try {
12302                 $browser.url(url, replace, state);
12303
12304                 // Make sure $location.state() returns referentially identical (not just deeply equal)
12305                 // state object; this makes possible quick checking if the state changed in the digest
12306                 // loop. Checking deep equality would be too expensive.
12307                 $location.$$state = $browser.state();
12308               } catch (e) {
12309                 // Restore old values if pushState fails
12310                 $location.url(oldUrl);
12311                 $location.$$state = oldState;
12312
12313                 throw e;
12314               }
12315             }
12316
12317             $rootElement.on('click', function(event) {
12318               // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
12319               // currently we open nice url link and redirect then
12320
12321               if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;
12322
12323               var elm = jqLite(event.target);
12324
12325               // traverse the DOM up to find first A tag
12326               while (nodeName_(elm[0]) !== 'a') {
12327                 // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
12328                 if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
12329               }
12330
12331               var absHref = elm.prop('href');
12332               // get the actual href attribute - see
12333               // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
12334               var relHref = elm.attr('href') || elm.attr('xlink:href');
12335
12336               if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
12337                 // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
12338                 // an animation.
12339                 absHref = urlResolve(absHref.animVal).href;
12340               }
12341
12342               // Ignore when url is started with javascript: or mailto:
12343               if (IGNORE_URI_REGEXP.test(absHref)) return;
12344
12345               if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
12346                 if ($location.$$parseLinkUrl(absHref, relHref)) {
12347                   // We do a preventDefault for all urls that are part of the angular application,
12348                   // in html5mode and also without, so that we are able to abort navigation without
12349                   // getting double entries in the location history.
12350                   event.preventDefault();
12351                   // update location manually
12352                   if ($location.absUrl() != $browser.url()) {
12353                     $rootScope.$apply();
12354                     // hack to work around FF6 bug 684208 when scenario runner clicks on links
12355                     $window.angular['ff-684208-preventDefault'] = true;
12356                   }
12357                 }
12358               }
12359             });
12360
12361
12362             // rewrite hashbang url <> html5 url
12363             if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
12364               $browser.url($location.absUrl(), true);
12365             }
12366
12367             var initializing = true;
12368
12369             // update $location when $browser url changes
12370             $browser.onUrlChange(function(newUrl, newState) {
12371
12372               if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
12373                 // If we are navigating outside of the app then force a reload
12374                 $window.location.href = newUrl;
12375                 return;
12376               }
12377
12378               $rootScope.$evalAsync(function() {
12379                 var oldUrl = $location.absUrl();
12380                 var oldState = $location.$$state;
12381                 var defaultPrevented;
12382                 newUrl = trimEmptyHash(newUrl);
12383                 $location.$$parse(newUrl);
12384                 $location.$$state = newState;
12385
12386                 defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
12387                     newState, oldState).defaultPrevented;
12388
12389                 // if the location was changed by a `$locationChangeStart` handler then stop
12390                 // processing this location change
12391                 if ($location.absUrl() !== newUrl) return;
12392
12393                 if (defaultPrevented) {
12394                   $location.$$parse(oldUrl);
12395                   $location.$$state = oldState;
12396                   setBrowserUrlWithFallback(oldUrl, false, oldState);
12397                 } else {
12398                   initializing = false;
12399                   afterLocationChange(oldUrl, oldState);
12400                 }
12401               });
12402               if (!$rootScope.$$phase) $rootScope.$digest();
12403             });
12404
12405             // update browser
12406             $rootScope.$watch(function $locationWatch() {
12407               var oldUrl = trimEmptyHash($browser.url());
12408               var newUrl = trimEmptyHash($location.absUrl());
12409               var oldState = $browser.state();
12410               var currentReplace = $location.$$replace;
12411               var urlOrStateChanged = oldUrl !== newUrl ||
12412                 ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
12413
12414               if (initializing || urlOrStateChanged) {
12415                 initializing = false;
12416
12417                 $rootScope.$evalAsync(function() {
12418                   var newUrl = $location.absUrl();
12419                   var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
12420                       $location.$$state, oldState).defaultPrevented;
12421
12422                   // if the location was changed by a `$locationChangeStart` handler then stop
12423                   // processing this location change
12424                   if ($location.absUrl() !== newUrl) return;
12425
12426                   if (defaultPrevented) {
12427                     $location.$$parse(oldUrl);
12428                     $location.$$state = oldState;
12429                   } else {
12430                     if (urlOrStateChanged) {
12431                       setBrowserUrlWithFallback(newUrl, currentReplace,
12432                                                 oldState === $location.$$state ? null : $location.$$state);
12433                     }
12434                     afterLocationChange(oldUrl, oldState);
12435                   }
12436                 });
12437               }
12438
12439               $location.$$replace = false;
12440
12441               // we don't need to return anything because $evalAsync will make the digest loop dirty when
12442               // there is a change
12443             });
12444
12445             return $location;
12446
12447             function afterLocationChange(oldUrl, oldState) {
12448               $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,
12449                 $location.$$state, oldState);
12450             }
12451         }];
12452         }
12453
12454         /**
12455          * @ngdoc service
12456          * @name $log
12457          * @requires $window
12458          *
12459          * @description
12460          * Simple service for logging. Default implementation safely writes the message
12461          * into the browser's console (if present).
12462          *
12463          * The main purpose of this service is to simplify debugging and troubleshooting.
12464          *
12465          * The default is to log `debug` messages. You can use
12466          * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
12467          *
12468          * @example
12469            <example module="logExample">
12470              <file name="script.js">
12471                angular.module('logExample', [])
12472                  .controller('LogController', ['$scope', '$log', function($scope, $log) {
12473                    $scope.$log = $log;
12474                    $scope.message = 'Hello World!';
12475                  }]);
12476              </file>
12477              <file name="index.html">
12478                <div ng-controller="LogController">
12479                  <p>Reload this page with open console, enter text and hit the log button...</p>
12480                  <label>Message:
12481                  <input type="text" ng-model="message" /></label>
12482                  <button ng-click="$log.log(message)">log</button>
12483                  <button ng-click="$log.warn(message)">warn</button>
12484                  <button ng-click="$log.info(message)">info</button>
12485                  <button ng-click="$log.error(message)">error</button>
12486                  <button ng-click="$log.debug(message)">debug</button>
12487                </div>
12488              </file>
12489            </example>
12490          */
12491
12492         /**
12493          * @ngdoc provider
12494          * @name $logProvider
12495          * @description
12496          * Use the `$logProvider` to configure how the application logs messages
12497          */
12498         function $LogProvider() {
12499           var debug = true,
12500               self = this;
12501
12502           /**
12503            * @ngdoc method
12504            * @name $logProvider#debugEnabled
12505            * @description
12506            * @param {boolean=} flag enable or disable debug level messages
12507            * @returns {*} current value if used as getter or itself (chaining) if used as setter
12508            */
12509           this.debugEnabled = function(flag) {
12510             if (isDefined(flag)) {
12511               debug = flag;
12512             return this;
12513             } else {
12514               return debug;
12515             }
12516           };
12517
12518           this.$get = ['$window', function($window) {
12519             return {
12520               /**
12521                * @ngdoc method
12522                * @name $log#log
12523                *
12524                * @description
12525                * Write a log message
12526                */
12527               log: consoleLog('log'),
12528
12529               /**
12530                * @ngdoc method
12531                * @name $log#info
12532                *
12533                * @description
12534                * Write an information message
12535                */
12536               info: consoleLog('info'),
12537
12538               /**
12539                * @ngdoc method
12540                * @name $log#warn
12541                *
12542                * @description
12543                * Write a warning message
12544                */
12545               warn: consoleLog('warn'),
12546
12547               /**
12548                * @ngdoc method
12549                * @name $log#error
12550                *
12551                * @description
12552                * Write an error message
12553                */
12554               error: consoleLog('error'),
12555
12556               /**
12557                * @ngdoc method
12558                * @name $log#debug
12559                *
12560                * @description
12561                * Write a debug message
12562                */
12563               debug: (function() {
12564                 var fn = consoleLog('debug');
12565
12566                 return function() {
12567                   if (debug) {
12568                     fn.apply(self, arguments);
12569                   }
12570                 };
12571               }())
12572             };
12573
12574             function formatError(arg) {
12575               if (arg instanceof Error) {
12576                 if (arg.stack) {
12577                   arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
12578                       ? 'Error: ' + arg.message + '\n' + arg.stack
12579                       : arg.stack;
12580                 } else if (arg.sourceURL) {
12581                   arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
12582                 }
12583               }
12584               return arg;
12585             }
12586
12587             function consoleLog(type) {
12588               var console = $window.console || {},
12589                   logFn = console[type] || console.log || noop,
12590                   hasApply = false;
12591
12592               // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
12593               // The reason behind this is that console.log has type "object" in IE8...
12594               try {
12595                 hasApply = !!logFn.apply;
12596               } catch (e) {}
12597
12598               if (hasApply) {
12599                 return function() {
12600                   var args = [];
12601                   forEach(arguments, function(arg) {
12602                     args.push(formatError(arg));
12603                   });
12604                   return logFn.apply(console, args);
12605                 };
12606               }
12607
12608               // we are IE which either doesn't have window.console => this is noop and we do nothing,
12609               // or we are IE where console.log doesn't have apply so we log at least first 2 args
12610               return function(arg1, arg2) {
12611                 logFn(arg1, arg2 == null ? '' : arg2);
12612               };
12613             }
12614           }];
12615         }
12616
12617         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
12618          *     Any commits to this file should be reviewed with security in mind.  *
12619          *   Changes to this file can potentially create security vulnerabilities. *
12620          *          An approval from 2 Core members with history of modifying      *
12621          *                         this file is required.                          *
12622          *                                                                         *
12623          *  Does the change somehow allow for arbitrary javascript to be executed? *
12624          *    Or allows for someone to change the prototype of built-in objects?   *
12625          *     Or gives undesired access to variables likes document or window?    *
12626          * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12627
12628         var $parseMinErr = minErr('$parse');
12629
12630         // Sandboxing Angular Expressions
12631         // ------------------------------
12632         // Angular expressions are generally considered safe because these expressions only have direct
12633         // access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
12634         // obtaining a reference to native JS functions such as the Function constructor.
12635         //
12636         // As an example, consider the following Angular expression:
12637         //
12638         //   {}.toString.constructor('alert("evil JS code")')
12639         //
12640         // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
12641         // against the expression language, but not to prevent exploits that were enabled by exposing
12642         // sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
12643         // practice and therefore we are not even trying to protect against interaction with an object
12644         // explicitly exposed in this way.
12645         //
12646         // In general, it is not possible to access a Window object from an angular expression unless a
12647         // window or some DOM object that has a reference to window is published onto a Scope.
12648         // Similarly we prevent invocations of function known to be dangerous, as well as assignments to
12649         // native objects.
12650         //
12651         // See https://docs.angularjs.org/guide/security
12652
12653
12654         function ensureSafeMemberName(name, fullExpression) {
12655           if (name === "__defineGetter__" || name === "__defineSetter__"
12656               || name === "__lookupGetter__" || name === "__lookupSetter__"
12657               || name === "__proto__") {
12658             throw $parseMinErr('isecfld',
12659                 'Attempting to access a disallowed field in Angular expressions! '
12660                 + 'Expression: {0}', fullExpression);
12661           }
12662           return name;
12663         }
12664
12665         function getStringValue(name, fullExpression) {
12666           // From the JavaScript docs:
12667           // Property names must be strings. This means that non-string objects cannot be used
12668           // as keys in an object. Any non-string object, including a number, is typecasted
12669           // into a string via the toString method.
12670           //
12671           // So, to ensure that we are checking the same `name` that JavaScript would use,
12672           // we cast it to a string, if possible.
12673           // Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
12674           // this is, this will handle objects that misbehave.
12675           name = name + '';
12676           if (!isString(name)) {
12677             throw $parseMinErr('iseccst',
12678                 'Cannot convert object to primitive value! '
12679                 + 'Expression: {0}', fullExpression);
12680           }
12681           return name;
12682         }
12683
12684         function ensureSafeObject(obj, fullExpression) {
12685           // nifty check if obj is Function that is fast and works across iframes and other contexts
12686           if (obj) {
12687             if (obj.constructor === obj) {
12688               throw $parseMinErr('isecfn',
12689                   'Referencing Function in Angular expressions is disallowed! Expression: {0}',
12690                   fullExpression);
12691             } else if (// isWindow(obj)
12692                 obj.window === obj) {
12693               throw $parseMinErr('isecwindow',
12694                   'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
12695                   fullExpression);
12696             } else if (// isElement(obj)
12697                 obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
12698               throw $parseMinErr('isecdom',
12699                   'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
12700                   fullExpression);
12701             } else if (// block Object so that we can't get hold of dangerous Object.* methods
12702                 obj === Object) {
12703               throw $parseMinErr('isecobj',
12704                   'Referencing Object in Angular expressions is disallowed! Expression: {0}',
12705                   fullExpression);
12706             }
12707           }
12708           return obj;
12709         }
12710
12711         var CALL = Function.prototype.call;
12712         var APPLY = Function.prototype.apply;
12713         var BIND = Function.prototype.bind;
12714
12715         function ensureSafeFunction(obj, fullExpression) {
12716           if (obj) {
12717             if (obj.constructor === obj) {
12718               throw $parseMinErr('isecfn',
12719                 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
12720                 fullExpression);
12721             } else if (obj === CALL || obj === APPLY || obj === BIND) {
12722               throw $parseMinErr('isecff',
12723                 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
12724                 fullExpression);
12725             }
12726           }
12727         }
12728
12729         function ensureSafeAssignContext(obj, fullExpression) {
12730           if (obj) {
12731             if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor ||
12732                 obj === {}.constructor || obj === [].constructor || obj === Function.constructor) {
12733               throw $parseMinErr('isecaf',
12734                 'Assigning to a constructor is disallowed! Expression: {0}', fullExpression);
12735             }
12736           }
12737         }
12738
12739         var OPERATORS = createMap();
12740         forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });
12741         var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
12742
12743
12744         /////////////////////////////////////////
12745
12746
12747         /**
12748          * @constructor
12749          */
12750         var Lexer = function(options) {
12751           this.options = options;
12752         };
12753
12754         Lexer.prototype = {
12755           constructor: Lexer,
12756
12757           lex: function(text) {
12758             this.text = text;
12759             this.index = 0;
12760             this.tokens = [];
12761
12762             while (this.index < this.text.length) {
12763               var ch = this.text.charAt(this.index);
12764               if (ch === '"' || ch === "'") {
12765                 this.readString(ch);
12766               } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
12767                 this.readNumber();
12768               } else if (this.isIdent(ch)) {
12769                 this.readIdent();
12770               } else if (this.is(ch, '(){}[].,;:?')) {
12771                 this.tokens.push({index: this.index, text: ch});
12772                 this.index++;
12773               } else if (this.isWhitespace(ch)) {
12774                 this.index++;
12775               } else {
12776                 var ch2 = ch + this.peek();
12777                 var ch3 = ch2 + this.peek(2);
12778                 var op1 = OPERATORS[ch];
12779                 var op2 = OPERATORS[ch2];
12780                 var op3 = OPERATORS[ch3];
12781                 if (op1 || op2 || op3) {
12782                   var token = op3 ? ch3 : (op2 ? ch2 : ch);
12783                   this.tokens.push({index: this.index, text: token, operator: true});
12784                   this.index += token.length;
12785                 } else {
12786                   this.throwError('Unexpected next character ', this.index, this.index + 1);
12787                 }
12788               }
12789             }
12790             return this.tokens;
12791           },
12792
12793           is: function(ch, chars) {
12794             return chars.indexOf(ch) !== -1;
12795           },
12796
12797           peek: function(i) {
12798             var num = i || 1;
12799             return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
12800           },
12801
12802           isNumber: function(ch) {
12803             return ('0' <= ch && ch <= '9') && typeof ch === "string";
12804           },
12805
12806           isWhitespace: function(ch) {
12807             // IE treats non-breaking space as \u00A0
12808             return (ch === ' ' || ch === '\r' || ch === '\t' ||
12809                     ch === '\n' || ch === '\v' || ch === '\u00A0');
12810           },
12811
12812           isIdent: function(ch) {
12813             return ('a' <= ch && ch <= 'z' ||
12814                     'A' <= ch && ch <= 'Z' ||
12815                     '_' === ch || ch === '$');
12816           },
12817
12818           isExpOperator: function(ch) {
12819             return (ch === '-' || ch === '+' || this.isNumber(ch));
12820           },
12821
12822           throwError: function(error, start, end) {
12823             end = end || this.index;
12824             var colStr = (isDefined(start)
12825                     ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'
12826                     : ' ' + end);
12827             throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
12828                 error, colStr, this.text);
12829           },
12830
12831           readNumber: function() {
12832             var number = '';
12833             var start = this.index;
12834             while (this.index < this.text.length) {
12835               var ch = lowercase(this.text.charAt(this.index));
12836               if (ch == '.' || this.isNumber(ch)) {
12837                 number += ch;
12838               } else {
12839                 var peekCh = this.peek();
12840                 if (ch == 'e' && this.isExpOperator(peekCh)) {
12841                   number += ch;
12842                 } else if (this.isExpOperator(ch) &&
12843                     peekCh && this.isNumber(peekCh) &&
12844                     number.charAt(number.length - 1) == 'e') {
12845                   number += ch;
12846                 } else if (this.isExpOperator(ch) &&
12847                     (!peekCh || !this.isNumber(peekCh)) &&
12848                     number.charAt(number.length - 1) == 'e') {
12849                   this.throwError('Invalid exponent');
12850                 } else {
12851                   break;
12852                 }
12853               }
12854               this.index++;
12855             }
12856             this.tokens.push({
12857               index: start,
12858               text: number,
12859               constant: true,
12860               value: Number(number)
12861             });
12862           },
12863
12864           readIdent: function() {
12865             var start = this.index;
12866             while (this.index < this.text.length) {
12867               var ch = this.text.charAt(this.index);
12868               if (!(this.isIdent(ch) || this.isNumber(ch))) {
12869                 break;
12870               }
12871               this.index++;
12872             }
12873             this.tokens.push({
12874               index: start,
12875               text: this.text.slice(start, this.index),
12876               identifier: true
12877             });
12878           },
12879
12880           readString: function(quote) {
12881             var start = this.index;
12882             this.index++;
12883             var string = '';
12884             var rawString = quote;
12885             var escape = false;
12886             while (this.index < this.text.length) {
12887               var ch = this.text.charAt(this.index);
12888               rawString += ch;
12889               if (escape) {
12890                 if (ch === 'u') {
12891                   var hex = this.text.substring(this.index + 1, this.index + 5);
12892                   if (!hex.match(/[\da-f]{4}/i)) {
12893                     this.throwError('Invalid unicode escape [\\u' + hex + ']');
12894                   }
12895                   this.index += 4;
12896                   string += String.fromCharCode(parseInt(hex, 16));
12897                 } else {
12898                   var rep = ESCAPE[ch];
12899                   string = string + (rep || ch);
12900                 }
12901                 escape = false;
12902               } else if (ch === '\\') {
12903                 escape = true;
12904               } else if (ch === quote) {
12905                 this.index++;
12906                 this.tokens.push({
12907                   index: start,
12908                   text: rawString,
12909                   constant: true,
12910                   value: string
12911                 });
12912                 return;
12913               } else {
12914                 string += ch;
12915               }
12916               this.index++;
12917             }
12918             this.throwError('Unterminated quote', start);
12919           }
12920         };
12921
12922         var AST = function(lexer, options) {
12923           this.lexer = lexer;
12924           this.options = options;
12925         };
12926
12927         AST.Program = 'Program';
12928         AST.ExpressionStatement = 'ExpressionStatement';
12929         AST.AssignmentExpression = 'AssignmentExpression';
12930         AST.ConditionalExpression = 'ConditionalExpression';
12931         AST.LogicalExpression = 'LogicalExpression';
12932         AST.BinaryExpression = 'BinaryExpression';
12933         AST.UnaryExpression = 'UnaryExpression';
12934         AST.CallExpression = 'CallExpression';
12935         AST.MemberExpression = 'MemberExpression';
12936         AST.Identifier = 'Identifier';
12937         AST.Literal = 'Literal';
12938         AST.ArrayExpression = 'ArrayExpression';
12939         AST.Property = 'Property';
12940         AST.ObjectExpression = 'ObjectExpression';
12941         AST.ThisExpression = 'ThisExpression';
12942
12943         // Internal use only
12944         AST.NGValueParameter = 'NGValueParameter';
12945
12946         AST.prototype = {
12947           ast: function(text) {
12948             this.text = text;
12949             this.tokens = this.lexer.lex(text);
12950
12951             var value = this.program();
12952
12953             if (this.tokens.length !== 0) {
12954               this.throwError('is an unexpected token', this.tokens[0]);
12955             }
12956
12957             return value;
12958           },
12959
12960           program: function() {
12961             var body = [];
12962             while (true) {
12963               if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
12964                 body.push(this.expressionStatement());
12965               if (!this.expect(';')) {
12966                 return { type: AST.Program, body: body};
12967               }
12968             }
12969           },
12970
12971           expressionStatement: function() {
12972             return { type: AST.ExpressionStatement, expression: this.filterChain() };
12973           },
12974
12975           filterChain: function() {
12976             var left = this.expression();
12977             var token;
12978             while ((token = this.expect('|'))) {
12979               left = this.filter(left);
12980             }
12981             return left;
12982           },
12983
12984           expression: function() {
12985             return this.assignment();
12986           },
12987
12988           assignment: function() {
12989             var result = this.ternary();
12990             if (this.expect('=')) {
12991               result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};
12992             }
12993             return result;
12994           },
12995
12996           ternary: function() {
12997             var test = this.logicalOR();
12998             var alternate;
12999             var consequent;
13000             if (this.expect('?')) {
13001               alternate = this.expression();
13002               if (this.consume(':')) {
13003                 consequent = this.expression();
13004                 return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent};
13005               }
13006             }
13007             return test;
13008           },
13009
13010           logicalOR: function() {
13011             var left = this.logicalAND();
13012             while (this.expect('||')) {
13013               left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() };
13014             }
13015             return left;
13016           },
13017
13018           logicalAND: function() {
13019             var left = this.equality();
13020             while (this.expect('&&')) {
13021               left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()};
13022             }
13023             return left;
13024           },
13025
13026           equality: function() {
13027             var left = this.relational();
13028             var token;
13029             while ((token = this.expect('==','!=','===','!=='))) {
13030               left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() };
13031             }
13032             return left;
13033           },
13034
13035           relational: function() {
13036             var left = this.additive();
13037             var token;
13038             while ((token = this.expect('<', '>', '<=', '>='))) {
13039               left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() };
13040             }
13041             return left;
13042           },
13043
13044           additive: function() {
13045             var left = this.multiplicative();
13046             var token;
13047             while ((token = this.expect('+','-'))) {
13048               left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() };
13049             }
13050             return left;
13051           },
13052
13053           multiplicative: function() {
13054             var left = this.unary();
13055             var token;
13056             while ((token = this.expect('*','/','%'))) {
13057               left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() };
13058             }
13059             return left;
13060           },
13061
13062           unary: function() {
13063             var token;
13064             if ((token = this.expect('+', '-', '!'))) {
13065               return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() };
13066             } else {
13067               return this.primary();
13068             }
13069           },
13070
13071           primary: function() {
13072             var primary;
13073             if (this.expect('(')) {
13074               primary = this.filterChain();
13075               this.consume(')');
13076             } else if (this.expect('[')) {
13077               primary = this.arrayDeclaration();
13078             } else if (this.expect('{')) {
13079               primary = this.object();
13080             } else if (this.constants.hasOwnProperty(this.peek().text)) {
13081               primary = copy(this.constants[this.consume().text]);
13082             } else if (this.peek().identifier) {
13083               primary = this.identifier();
13084             } else if (this.peek().constant) {
13085               primary = this.constant();
13086             } else {
13087               this.throwError('not a primary expression', this.peek());
13088             }
13089
13090             var next;
13091             while ((next = this.expect('(', '[', '.'))) {
13092               if (next.text === '(') {
13093                 primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() };
13094                 this.consume(')');
13095               } else if (next.text === '[') {
13096                 primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true };
13097                 this.consume(']');
13098               } else if (next.text === '.') {
13099                 primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false };
13100               } else {
13101                 this.throwError('IMPOSSIBLE');
13102               }
13103             }
13104             return primary;
13105           },
13106
13107           filter: function(baseExpression) {
13108             var args = [baseExpression];
13109             var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true};
13110
13111             while (this.expect(':')) {
13112               args.push(this.expression());
13113             }
13114
13115             return result;
13116           },
13117
13118           parseArguments: function() {
13119             var args = [];
13120             if (this.peekToken().text !== ')') {
13121               do {
13122                 args.push(this.expression());
13123               } while (this.expect(','));
13124             }
13125             return args;
13126           },
13127
13128           identifier: function() {
13129             var token = this.consume();
13130             if (!token.identifier) {
13131               this.throwError('is not a valid identifier', token);
13132             }
13133             return { type: AST.Identifier, name: token.text };
13134           },
13135
13136           constant: function() {
13137             // TODO check that it is a constant
13138             return { type: AST.Literal, value: this.consume().value };
13139           },
13140
13141           arrayDeclaration: function() {
13142             var elements = [];
13143             if (this.peekToken().text !== ']') {
13144               do {
13145                 if (this.peek(']')) {
13146                   // Support trailing commas per ES5.1.
13147                   break;
13148                 }
13149                 elements.push(this.expression());
13150               } while (this.expect(','));
13151             }
13152             this.consume(']');
13153
13154             return { type: AST.ArrayExpression, elements: elements };
13155           },
13156
13157           object: function() {
13158             var properties = [], property;
13159             if (this.peekToken().text !== '}') {
13160               do {
13161                 if (this.peek('}')) {
13162                   // Support trailing commas per ES5.1.
13163                   break;
13164                 }
13165                 property = {type: AST.Property, kind: 'init'};
13166                 if (this.peek().constant) {
13167                   property.key = this.constant();
13168                 } else if (this.peek().identifier) {
13169                   property.key = this.identifier();
13170                 } else {
13171                   this.throwError("invalid key", this.peek());
13172                 }
13173                 this.consume(':');
13174                 property.value = this.expression();
13175                 properties.push(property);
13176               } while (this.expect(','));
13177             }
13178             this.consume('}');
13179
13180             return {type: AST.ObjectExpression, properties: properties };
13181           },
13182
13183           throwError: function(msg, token) {
13184             throw $parseMinErr('syntax',
13185                 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
13186                   token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
13187           },
13188
13189           consume: function(e1) {
13190             if (this.tokens.length === 0) {
13191               throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
13192             }
13193
13194             var token = this.expect(e1);
13195             if (!token) {
13196               this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
13197             }
13198             return token;
13199           },
13200
13201           peekToken: function() {
13202             if (this.tokens.length === 0) {
13203               throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
13204             }
13205             return this.tokens[0];
13206           },
13207
13208           peek: function(e1, e2, e3, e4) {
13209             return this.peekAhead(0, e1, e2, e3, e4);
13210           },
13211
13212           peekAhead: function(i, e1, e2, e3, e4) {
13213             if (this.tokens.length > i) {
13214               var token = this.tokens[i];
13215               var t = token.text;
13216               if (t === e1 || t === e2 || t === e3 || t === e4 ||
13217                   (!e1 && !e2 && !e3 && !e4)) {
13218                 return token;
13219               }
13220             }
13221             return false;
13222           },
13223
13224           expect: function(e1, e2, e3, e4) {
13225             var token = this.peek(e1, e2, e3, e4);
13226             if (token) {
13227               this.tokens.shift();
13228               return token;
13229             }
13230             return false;
13231           },
13232
13233
13234           /* `undefined` is not a constant, it is an identifier,
13235            * but using it as an identifier is not supported
13236            */
13237           constants: {
13238             'true': { type: AST.Literal, value: true },
13239             'false': { type: AST.Literal, value: false },
13240             'null': { type: AST.Literal, value: null },
13241             'undefined': {type: AST.Literal, value: undefined },
13242             'this': {type: AST.ThisExpression }
13243           }
13244         };
13245
13246         function ifDefined(v, d) {
13247           return typeof v !== 'undefined' ? v : d;
13248         }
13249
13250         function plusFn(l, r) {
13251           if (typeof l === 'undefined') return r;
13252           if (typeof r === 'undefined') return l;
13253           return l + r;
13254         }
13255
13256         function isStateless($filter, filterName) {
13257           var fn = $filter(filterName);
13258           return !fn.$stateful;
13259         }
13260
13261         function findConstantAndWatchExpressions(ast, $filter) {
13262           var allConstants;
13263           var argsToWatch;
13264           switch (ast.type) {
13265           case AST.Program:
13266             allConstants = true;
13267             forEach(ast.body, function(expr) {
13268               findConstantAndWatchExpressions(expr.expression, $filter);
13269               allConstants = allConstants && expr.expression.constant;
13270             });
13271             ast.constant = allConstants;
13272             break;
13273           case AST.Literal:
13274             ast.constant = true;
13275             ast.toWatch = [];
13276             break;
13277           case AST.UnaryExpression:
13278             findConstantAndWatchExpressions(ast.argument, $filter);
13279             ast.constant = ast.argument.constant;
13280             ast.toWatch = ast.argument.toWatch;
13281             break;
13282           case AST.BinaryExpression:
13283             findConstantAndWatchExpressions(ast.left, $filter);
13284             findConstantAndWatchExpressions(ast.right, $filter);
13285             ast.constant = ast.left.constant && ast.right.constant;
13286             ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);
13287             break;
13288           case AST.LogicalExpression:
13289             findConstantAndWatchExpressions(ast.left, $filter);
13290             findConstantAndWatchExpressions(ast.right, $filter);
13291             ast.constant = ast.left.constant && ast.right.constant;
13292             ast.toWatch = ast.constant ? [] : [ast];
13293             break;
13294           case AST.ConditionalExpression:
13295             findConstantAndWatchExpressions(ast.test, $filter);
13296             findConstantAndWatchExpressions(ast.alternate, $filter);
13297             findConstantAndWatchExpressions(ast.consequent, $filter);
13298             ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant;
13299             ast.toWatch = ast.constant ? [] : [ast];
13300             break;
13301           case AST.Identifier:
13302             ast.constant = false;
13303             ast.toWatch = [ast];
13304             break;
13305           case AST.MemberExpression:
13306             findConstantAndWatchExpressions(ast.object, $filter);
13307             if (ast.computed) {
13308               findConstantAndWatchExpressions(ast.property, $filter);
13309             }
13310             ast.constant = ast.object.constant && (!ast.computed || ast.property.constant);
13311             ast.toWatch = [ast];
13312             break;
13313           case AST.CallExpression:
13314             allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false;
13315             argsToWatch = [];
13316             forEach(ast.arguments, function(expr) {
13317               findConstantAndWatchExpressions(expr, $filter);
13318               allConstants = allConstants && expr.constant;
13319               if (!expr.constant) {
13320                 argsToWatch.push.apply(argsToWatch, expr.toWatch);
13321               }
13322             });
13323             ast.constant = allConstants;
13324             ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast];
13325             break;
13326           case AST.AssignmentExpression:
13327             findConstantAndWatchExpressions(ast.left, $filter);
13328             findConstantAndWatchExpressions(ast.right, $filter);
13329             ast.constant = ast.left.constant && ast.right.constant;
13330             ast.toWatch = [ast];
13331             break;
13332           case AST.ArrayExpression:
13333             allConstants = true;
13334             argsToWatch = [];
13335             forEach(ast.elements, function(expr) {
13336               findConstantAndWatchExpressions(expr, $filter);
13337               allConstants = allConstants && expr.constant;
13338               if (!expr.constant) {
13339                 argsToWatch.push.apply(argsToWatch, expr.toWatch);
13340               }
13341             });
13342             ast.constant = allConstants;
13343             ast.toWatch = argsToWatch;
13344             break;
13345           case AST.ObjectExpression:
13346             allConstants = true;
13347             argsToWatch = [];
13348             forEach(ast.properties, function(property) {
13349               findConstantAndWatchExpressions(property.value, $filter);
13350               allConstants = allConstants && property.value.constant;
13351               if (!property.value.constant) {
13352                 argsToWatch.push.apply(argsToWatch, property.value.toWatch);
13353               }
13354             });
13355             ast.constant = allConstants;
13356             ast.toWatch = argsToWatch;
13357             break;
13358           case AST.ThisExpression:
13359             ast.constant = false;
13360             ast.toWatch = [];
13361             break;
13362           }
13363         }
13364
13365         function getInputs(body) {
13366           if (body.length != 1) return;
13367           var lastExpression = body[0].expression;
13368           var candidate = lastExpression.toWatch;
13369           if (candidate.length !== 1) return candidate;
13370           return candidate[0] !== lastExpression ? candidate : undefined;
13371         }
13372
13373         function isAssignable(ast) {
13374           return ast.type === AST.Identifier || ast.type === AST.MemberExpression;
13375         }
13376
13377         function assignableAST(ast) {
13378           if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {
13379             return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='};
13380           }
13381         }
13382
13383         function isLiteral(ast) {
13384           return ast.body.length === 0 ||
13385               ast.body.length === 1 && (
13386               ast.body[0].expression.type === AST.Literal ||
13387               ast.body[0].expression.type === AST.ArrayExpression ||
13388               ast.body[0].expression.type === AST.ObjectExpression);
13389         }
13390
13391         function isConstant(ast) {
13392           return ast.constant;
13393         }
13394
13395         function ASTCompiler(astBuilder, $filter) {
13396           this.astBuilder = astBuilder;
13397           this.$filter = $filter;
13398         }
13399
13400         ASTCompiler.prototype = {
13401           compile: function(expression, expensiveChecks) {
13402             var self = this;
13403             var ast = this.astBuilder.ast(expression);
13404             this.state = {
13405               nextId: 0,
13406               filters: {},
13407               expensiveChecks: expensiveChecks,
13408               fn: {vars: [], body: [], own: {}},
13409               assign: {vars: [], body: [], own: {}},
13410               inputs: []
13411             };
13412             findConstantAndWatchExpressions(ast, self.$filter);
13413             var extra = '';
13414             var assignable;
13415             this.stage = 'assign';
13416             if ((assignable = assignableAST(ast))) {
13417               this.state.computing = 'assign';
13418               var result = this.nextId();
13419               this.recurse(assignable, result);
13420               this.return_(result);
13421               extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');
13422             }
13423             var toWatch = getInputs(ast.body);
13424             self.stage = 'inputs';
13425             forEach(toWatch, function(watch, key) {
13426               var fnKey = 'fn' + key;
13427               self.state[fnKey] = {vars: [], body: [], own: {}};
13428               self.state.computing = fnKey;
13429               var intoId = self.nextId();
13430               self.recurse(watch, intoId);
13431               self.return_(intoId);
13432               self.state.inputs.push(fnKey);
13433               watch.watchId = key;
13434             });
13435             this.state.computing = 'fn';
13436             this.stage = 'main';
13437             this.recurse(ast);
13438             var fnString =
13439               // The build and minification steps remove the string "use strict" from the code, but this is done using a regex.
13440               // This is a workaround for this until we do a better job at only removing the prefix only when we should.
13441               '"' + this.USE + ' ' + this.STRICT + '";\n' +
13442               this.filterPrefix() +
13443               'var fn=' + this.generateFunction('fn', 's,l,a,i') +
13444               extra +
13445               this.watchFns() +
13446               'return fn;';
13447
13448             /* jshint -W054 */
13449             var fn = (new Function('$filter',
13450                 'ensureSafeMemberName',
13451                 'ensureSafeObject',
13452                 'ensureSafeFunction',
13453                 'getStringValue',
13454                 'ensureSafeAssignContext',
13455                 'ifDefined',
13456                 'plus',
13457                 'text',
13458                 fnString))(
13459                   this.$filter,
13460                   ensureSafeMemberName,
13461                   ensureSafeObject,
13462                   ensureSafeFunction,
13463                   getStringValue,
13464                   ensureSafeAssignContext,
13465                   ifDefined,
13466                   plusFn,
13467                   expression);
13468             /* jshint +W054 */
13469             this.state = this.stage = undefined;
13470             fn.literal = isLiteral(ast);
13471             fn.constant = isConstant(ast);
13472             return fn;
13473           },
13474
13475           USE: 'use',
13476
13477           STRICT: 'strict',
13478
13479           watchFns: function() {
13480             var result = [];
13481             var fns = this.state.inputs;
13482             var self = this;
13483             forEach(fns, function(name) {
13484               result.push('var ' + name + '=' + self.generateFunction(name, 's'));
13485             });
13486             if (fns.length) {
13487               result.push('fn.inputs=[' + fns.join(',') + '];');
13488             }
13489             return result.join('');
13490           },
13491
13492           generateFunction: function(name, params) {
13493             return 'function(' + params + '){' +
13494                 this.varsPrefix(name) +
13495                 this.body(name) +
13496                 '};';
13497           },
13498
13499           filterPrefix: function() {
13500             var parts = [];
13501             var self = this;
13502             forEach(this.state.filters, function(id, filter) {
13503               parts.push(id + '=$filter(' + self.escape(filter) + ')');
13504             });
13505             if (parts.length) return 'var ' + parts.join(',') + ';';
13506             return '';
13507           },
13508
13509           varsPrefix: function(section) {
13510             return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : '';
13511           },
13512
13513           body: function(section) {
13514             return this.state[section].body.join('');
13515           },
13516
13517           recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
13518             var left, right, self = this, args, expression;
13519             recursionFn = recursionFn || noop;
13520             if (!skipWatchIdCheck && isDefined(ast.watchId)) {
13521               intoId = intoId || this.nextId();
13522               this.if_('i',
13523                 this.lazyAssign(intoId, this.computedMember('i', ast.watchId)),
13524                 this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)
13525               );
13526               return;
13527             }
13528             switch (ast.type) {
13529             case AST.Program:
13530               forEach(ast.body, function(expression, pos) {
13531                 self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; });
13532                 if (pos !== ast.body.length - 1) {
13533                   self.current().body.push(right, ';');
13534                 } else {
13535                   self.return_(right);
13536                 }
13537               });
13538               break;
13539             case AST.Literal:
13540               expression = this.escape(ast.value);
13541               this.assign(intoId, expression);
13542               recursionFn(expression);
13543               break;
13544             case AST.UnaryExpression:
13545               this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; });
13546               expression = ast.operator + '(' + this.ifDefined(right, 0) + ')';
13547               this.assign(intoId, expression);
13548               recursionFn(expression);
13549               break;
13550             case AST.BinaryExpression:
13551               this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; });
13552               this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; });
13553               if (ast.operator === '+') {
13554                 expression = this.plus(left, right);
13555               } else if (ast.operator === '-') {
13556                 expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0);
13557               } else {
13558                 expression = '(' + left + ')' + ast.operator + '(' + right + ')';
13559               }
13560               this.assign(intoId, expression);
13561               recursionFn(expression);
13562               break;
13563             case AST.LogicalExpression:
13564               intoId = intoId || this.nextId();
13565               self.recurse(ast.left, intoId);
13566               self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId));
13567               recursionFn(intoId);
13568               break;
13569             case AST.ConditionalExpression:
13570               intoId = intoId || this.nextId();
13571               self.recurse(ast.test, intoId);
13572               self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId));
13573               recursionFn(intoId);
13574               break;
13575             case AST.Identifier:
13576               intoId = intoId || this.nextId();
13577               if (nameId) {
13578                 nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s');
13579                 nameId.computed = false;
13580                 nameId.name = ast.name;
13581               }
13582               ensureSafeMemberName(ast.name);
13583               self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)),
13584                 function() {
13585                   self.if_(self.stage === 'inputs' || 's', function() {
13586                     if (create && create !== 1) {
13587                       self.if_(
13588                         self.not(self.nonComputedMember('s', ast.name)),
13589                         self.lazyAssign(self.nonComputedMember('s', ast.name), '{}'));
13590                     }
13591                     self.assign(intoId, self.nonComputedMember('s', ast.name));
13592                   });
13593                 }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name))
13594                 );
13595               if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) {
13596                 self.addEnsureSafeObject(intoId);
13597               }
13598               recursionFn(intoId);
13599               break;
13600             case AST.MemberExpression:
13601               left = nameId && (nameId.context = this.nextId()) || this.nextId();
13602               intoId = intoId || this.nextId();
13603               self.recurse(ast.object, left, undefined, function() {
13604                 self.if_(self.notNull(left), function() {
13605                   if (ast.computed) {
13606                     right = self.nextId();
13607                     self.recurse(ast.property, right);
13608                     self.getStringValue(right);
13609                     self.addEnsureSafeMemberName(right);
13610                     if (create && create !== 1) {
13611                       self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));
13612                     }
13613                     expression = self.ensureSafeObject(self.computedMember(left, right));
13614                     self.assign(intoId, expression);
13615                     if (nameId) {
13616                       nameId.computed = true;
13617                       nameId.name = right;
13618                     }
13619                   } else {
13620                     ensureSafeMemberName(ast.property.name);
13621                     if (create && create !== 1) {
13622                       self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));
13623                     }
13624                     expression = self.nonComputedMember(left, ast.property.name);
13625                     if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) {
13626                       expression = self.ensureSafeObject(expression);
13627                     }
13628                     self.assign(intoId, expression);
13629                     if (nameId) {
13630                       nameId.computed = false;
13631                       nameId.name = ast.property.name;
13632                     }
13633                   }
13634                 }, function() {
13635                   self.assign(intoId, 'undefined');
13636                 });
13637                 recursionFn(intoId);
13638               }, !!create);
13639               break;
13640             case AST.CallExpression:
13641               intoId = intoId || this.nextId();
13642               if (ast.filter) {
13643                 right = self.filter(ast.callee.name);
13644                 args = [];
13645                 forEach(ast.arguments, function(expr) {
13646                   var argument = self.nextId();
13647                   self.recurse(expr, argument);
13648                   args.push(argument);
13649                 });
13650                 expression = right + '(' + args.join(',') + ')';
13651                 self.assign(intoId, expression);
13652                 recursionFn(intoId);
13653               } else {
13654                 right = self.nextId();
13655                 left = {};
13656                 args = [];
13657                 self.recurse(ast.callee, right, left, function() {
13658                   self.if_(self.notNull(right), function() {
13659                     self.addEnsureSafeFunction(right);
13660                     forEach(ast.arguments, function(expr) {
13661                       self.recurse(expr, self.nextId(), undefined, function(argument) {
13662                         args.push(self.ensureSafeObject(argument));
13663                       });
13664                     });
13665                     if (left.name) {
13666                       if (!self.state.expensiveChecks) {
13667                         self.addEnsureSafeObject(left.context);
13668                       }
13669                       expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')';
13670                     } else {
13671                       expression = right + '(' + args.join(',') + ')';
13672                     }
13673                     expression = self.ensureSafeObject(expression);
13674                     self.assign(intoId, expression);
13675                   }, function() {
13676                     self.assign(intoId, 'undefined');
13677                   });
13678                   recursionFn(intoId);
13679                 });
13680               }
13681               break;
13682             case AST.AssignmentExpression:
13683               right = this.nextId();
13684               left = {};
13685               if (!isAssignable(ast.left)) {
13686                 throw $parseMinErr('lval', 'Trying to assing a value to a non l-value');
13687               }
13688               this.recurse(ast.left, undefined, left, function() {
13689                 self.if_(self.notNull(left.context), function() {
13690                   self.recurse(ast.right, right);
13691                   self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));
13692                   self.addEnsureSafeAssignContext(left.context);
13693                   expression = self.member(left.context, left.name, left.computed) + ast.operator + right;
13694                   self.assign(intoId, expression);
13695                   recursionFn(intoId || expression);
13696                 });
13697               }, 1);
13698               break;
13699             case AST.ArrayExpression:
13700               args = [];
13701               forEach(ast.elements, function(expr) {
13702                 self.recurse(expr, self.nextId(), undefined, function(argument) {
13703                   args.push(argument);
13704                 });
13705               });
13706               expression = '[' + args.join(',') + ']';
13707               this.assign(intoId, expression);
13708               recursionFn(expression);
13709               break;
13710             case AST.ObjectExpression:
13711               args = [];
13712               forEach(ast.properties, function(property) {
13713                 self.recurse(property.value, self.nextId(), undefined, function(expr) {
13714                   args.push(self.escape(
13715                       property.key.type === AST.Identifier ? property.key.name :
13716                         ('' + property.key.value)) +
13717                       ':' + expr);
13718                 });
13719               });
13720               expression = '{' + args.join(',') + '}';
13721               this.assign(intoId, expression);
13722               recursionFn(expression);
13723               break;
13724             case AST.ThisExpression:
13725               this.assign(intoId, 's');
13726               recursionFn('s');
13727               break;
13728             case AST.NGValueParameter:
13729               this.assign(intoId, 'v');
13730               recursionFn('v');
13731               break;
13732             }
13733           },
13734
13735           getHasOwnProperty: function(element, property) {
13736             var key = element + '.' + property;
13737             var own = this.current().own;
13738             if (!own.hasOwnProperty(key)) {
13739               own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')');
13740             }
13741             return own[key];
13742           },
13743
13744           assign: function(id, value) {
13745             if (!id) return;
13746             this.current().body.push(id, '=', value, ';');
13747             return id;
13748           },
13749
13750           filter: function(filterName) {
13751             if (!this.state.filters.hasOwnProperty(filterName)) {
13752               this.state.filters[filterName] = this.nextId(true);
13753             }
13754             return this.state.filters[filterName];
13755           },
13756
13757           ifDefined: function(id, defaultValue) {
13758             return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')';
13759           },
13760
13761           plus: function(left, right) {
13762             return 'plus(' + left + ',' + right + ')';
13763           },
13764
13765           return_: function(id) {
13766             this.current().body.push('return ', id, ';');
13767           },
13768
13769           if_: function(test, alternate, consequent) {
13770             if (test === true) {
13771               alternate();
13772             } else {
13773               var body = this.current().body;
13774               body.push('if(', test, '){');
13775               alternate();
13776               body.push('}');
13777               if (consequent) {
13778                 body.push('else{');
13779                 consequent();
13780                 body.push('}');
13781               }
13782             }
13783           },
13784
13785           not: function(expression) {
13786             return '!(' + expression + ')';
13787           },
13788
13789           notNull: function(expression) {
13790             return expression + '!=null';
13791           },
13792
13793           nonComputedMember: function(left, right) {
13794             return left + '.' + right;
13795           },
13796
13797           computedMember: function(left, right) {
13798             return left + '[' + right + ']';
13799           },
13800
13801           member: function(left, right, computed) {
13802             if (computed) return this.computedMember(left, right);
13803             return this.nonComputedMember(left, right);
13804           },
13805
13806           addEnsureSafeObject: function(item) {
13807             this.current().body.push(this.ensureSafeObject(item), ';');
13808           },
13809
13810           addEnsureSafeMemberName: function(item) {
13811             this.current().body.push(this.ensureSafeMemberName(item), ';');
13812           },
13813
13814           addEnsureSafeFunction: function(item) {
13815             this.current().body.push(this.ensureSafeFunction(item), ';');
13816           },
13817
13818           addEnsureSafeAssignContext: function(item) {
13819             this.current().body.push(this.ensureSafeAssignContext(item), ';');
13820           },
13821
13822           ensureSafeObject: function(item) {
13823             return 'ensureSafeObject(' + item + ',text)';
13824           },
13825
13826           ensureSafeMemberName: function(item) {
13827             return 'ensureSafeMemberName(' + item + ',text)';
13828           },
13829
13830           ensureSafeFunction: function(item) {
13831             return 'ensureSafeFunction(' + item + ',text)';
13832           },
13833
13834           getStringValue: function(item) {
13835             this.assign(item, 'getStringValue(' + item + ',text)');
13836           },
13837
13838           ensureSafeAssignContext: function(item) {
13839             return 'ensureSafeAssignContext(' + item + ',text)';
13840           },
13841
13842           lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
13843             var self = this;
13844             return function() {
13845               self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck);
13846             };
13847           },
13848
13849           lazyAssign: function(id, value) {
13850             var self = this;
13851             return function() {
13852               self.assign(id, value);
13853             };
13854           },
13855
13856           stringEscapeRegex: /[^ a-zA-Z0-9]/g,
13857
13858           stringEscapeFn: function(c) {
13859             return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4);
13860           },
13861
13862           escape: function(value) {
13863             if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'";
13864             if (isNumber(value)) return value.toString();
13865             if (value === true) return 'true';
13866             if (value === false) return 'false';
13867             if (value === null) return 'null';
13868             if (typeof value === 'undefined') return 'undefined';
13869
13870             throw $parseMinErr('esc', 'IMPOSSIBLE');
13871           },
13872
13873           nextId: function(skip, init) {
13874             var id = 'v' + (this.state.nextId++);
13875             if (!skip) {
13876               this.current().vars.push(id + (init ? '=' + init : ''));
13877             }
13878             return id;
13879           },
13880
13881           current: function() {
13882             return this.state[this.state.computing];
13883           }
13884         };
13885
13886
13887         function ASTInterpreter(astBuilder, $filter) {
13888           this.astBuilder = astBuilder;
13889           this.$filter = $filter;
13890         }
13891
13892         ASTInterpreter.prototype = {
13893           compile: function(expression, expensiveChecks) {
13894             var self = this;
13895             var ast = this.astBuilder.ast(expression);
13896             this.expression = expression;
13897             this.expensiveChecks = expensiveChecks;
13898             findConstantAndWatchExpressions(ast, self.$filter);
13899             var assignable;
13900             var assign;
13901             if ((assignable = assignableAST(ast))) {
13902               assign = this.recurse(assignable);
13903             }
13904             var toWatch = getInputs(ast.body);
13905             var inputs;
13906             if (toWatch) {
13907               inputs = [];
13908               forEach(toWatch, function(watch, key) {
13909                 var input = self.recurse(watch);
13910                 watch.input = input;
13911                 inputs.push(input);
13912                 watch.watchId = key;
13913               });
13914             }
13915             var expressions = [];
13916             forEach(ast.body, function(expression) {
13917               expressions.push(self.recurse(expression.expression));
13918             });
13919             var fn = ast.body.length === 0 ? function() {} :
13920                      ast.body.length === 1 ? expressions[0] :
13921                      function(scope, locals) {
13922                        var lastValue;
13923                        forEach(expressions, function(exp) {
13924                          lastValue = exp(scope, locals);
13925                        });
13926                        return lastValue;
13927                      };
13928             if (assign) {
13929               fn.assign = function(scope, value, locals) {
13930                 return assign(scope, locals, value);
13931               };
13932             }
13933             if (inputs) {
13934               fn.inputs = inputs;
13935             }
13936             fn.literal = isLiteral(ast);
13937             fn.constant = isConstant(ast);
13938             return fn;
13939           },
13940
13941           recurse: function(ast, context, create) {
13942             var left, right, self = this, args, expression;
13943             if (ast.input) {
13944               return this.inputs(ast.input, ast.watchId);
13945             }
13946             switch (ast.type) {
13947             case AST.Literal:
13948               return this.value(ast.value, context);
13949             case AST.UnaryExpression:
13950               right = this.recurse(ast.argument);
13951               return this['unary' + ast.operator](right, context);
13952             case AST.BinaryExpression:
13953               left = this.recurse(ast.left);
13954               right = this.recurse(ast.right);
13955               return this['binary' + ast.operator](left, right, context);
13956             case AST.LogicalExpression:
13957               left = this.recurse(ast.left);
13958               right = this.recurse(ast.right);
13959               return this['binary' + ast.operator](left, right, context);
13960             case AST.ConditionalExpression:
13961               return this['ternary?:'](
13962                 this.recurse(ast.test),
13963                 this.recurse(ast.alternate),
13964                 this.recurse(ast.consequent),
13965                 context
13966               );
13967             case AST.Identifier:
13968               ensureSafeMemberName(ast.name, self.expression);
13969               return self.identifier(ast.name,
13970                                      self.expensiveChecks || isPossiblyDangerousMemberName(ast.name),
13971                                      context, create, self.expression);
13972             case AST.MemberExpression:
13973               left = this.recurse(ast.object, false, !!create);
13974               if (!ast.computed) {
13975                 ensureSafeMemberName(ast.property.name, self.expression);
13976                 right = ast.property.name;
13977               }
13978               if (ast.computed) right = this.recurse(ast.property);
13979               return ast.computed ?
13980                 this.computedMember(left, right, context, create, self.expression) :
13981                 this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression);
13982             case AST.CallExpression:
13983               args = [];
13984               forEach(ast.arguments, function(expr) {
13985                 args.push(self.recurse(expr));
13986               });
13987               if (ast.filter) right = this.$filter(ast.callee.name);
13988               if (!ast.filter) right = this.recurse(ast.callee, true);
13989               return ast.filter ?
13990                 function(scope, locals, assign, inputs) {
13991                   var values = [];
13992                   for (var i = 0; i < args.length; ++i) {
13993                     values.push(args[i](scope, locals, assign, inputs));
13994                   }
13995                   var value = right.apply(undefined, values, inputs);
13996                   return context ? {context: undefined, name: undefined, value: value} : value;
13997                 } :
13998                 function(scope, locals, assign, inputs) {
13999                   var rhs = right(scope, locals, assign, inputs);
14000                   var value;
14001                   if (rhs.value != null) {
14002                     ensureSafeObject(rhs.context, self.expression);
14003                     ensureSafeFunction(rhs.value, self.expression);
14004                     var values = [];
14005                     for (var i = 0; i < args.length; ++i) {
14006                       values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression));
14007                     }
14008                     value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression);
14009                   }
14010                   return context ? {value: value} : value;
14011                 };
14012             case AST.AssignmentExpression:
14013               left = this.recurse(ast.left, true, 1);
14014               right = this.recurse(ast.right);
14015               return function(scope, locals, assign, inputs) {
14016                 var lhs = left(scope, locals, assign, inputs);
14017                 var rhs = right(scope, locals, assign, inputs);
14018                 ensureSafeObject(lhs.value, self.expression);
14019                 ensureSafeAssignContext(lhs.context);
14020                 lhs.context[lhs.name] = rhs;
14021                 return context ? {value: rhs} : rhs;
14022               };
14023             case AST.ArrayExpression:
14024               args = [];
14025               forEach(ast.elements, function(expr) {
14026                 args.push(self.recurse(expr));
14027               });
14028               return function(scope, locals, assign, inputs) {
14029                 var value = [];
14030                 for (var i = 0; i < args.length; ++i) {
14031                   value.push(args[i](scope, locals, assign, inputs));
14032                 }
14033                 return context ? {value: value} : value;
14034               };
14035             case AST.ObjectExpression:
14036               args = [];
14037               forEach(ast.properties, function(property) {
14038                 args.push({key: property.key.type === AST.Identifier ?
14039                                 property.key.name :
14040                                 ('' + property.key.value),
14041                            value: self.recurse(property.value)
14042                 });
14043               });
14044               return function(scope, locals, assign, inputs) {
14045                 var value = {};
14046                 for (var i = 0; i < args.length; ++i) {
14047                   value[args[i].key] = args[i].value(scope, locals, assign, inputs);
14048                 }
14049                 return context ? {value: value} : value;
14050               };
14051             case AST.ThisExpression:
14052               return function(scope) {
14053                 return context ? {value: scope} : scope;
14054               };
14055             case AST.NGValueParameter:
14056               return function(scope, locals, assign, inputs) {
14057                 return context ? {value: assign} : assign;
14058               };
14059             }
14060           },
14061
14062           'unary+': function(argument, context) {
14063             return function(scope, locals, assign, inputs) {
14064               var arg = argument(scope, locals, assign, inputs);
14065               if (isDefined(arg)) {
14066                 arg = +arg;
14067               } else {
14068                 arg = 0;
14069               }
14070               return context ? {value: arg} : arg;
14071             };
14072           },
14073           'unary-': function(argument, context) {
14074             return function(scope, locals, assign, inputs) {
14075               var arg = argument(scope, locals, assign, inputs);
14076               if (isDefined(arg)) {
14077                 arg = -arg;
14078               } else {
14079                 arg = 0;
14080               }
14081               return context ? {value: arg} : arg;
14082             };
14083           },
14084           'unary!': function(argument, context) {
14085             return function(scope, locals, assign, inputs) {
14086               var arg = !argument(scope, locals, assign, inputs);
14087               return context ? {value: arg} : arg;
14088             };
14089           },
14090           'binary+': function(left, right, context) {
14091             return function(scope, locals, assign, inputs) {
14092               var lhs = left(scope, locals, assign, inputs);
14093               var rhs = right(scope, locals, assign, inputs);
14094               var arg = plusFn(lhs, rhs);
14095               return context ? {value: arg} : arg;
14096             };
14097           },
14098           'binary-': function(left, right, context) {
14099             return function(scope, locals, assign, inputs) {
14100               var lhs = left(scope, locals, assign, inputs);
14101               var rhs = right(scope, locals, assign, inputs);
14102               var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0);
14103               return context ? {value: arg} : arg;
14104             };
14105           },
14106           'binary*': function(left, right, context) {
14107             return function(scope, locals, assign, inputs) {
14108               var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs);
14109               return context ? {value: arg} : arg;
14110             };
14111           },
14112           'binary/': function(left, right, context) {
14113             return function(scope, locals, assign, inputs) {
14114               var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs);
14115               return context ? {value: arg} : arg;
14116             };
14117           },
14118           'binary%': function(left, right, context) {
14119             return function(scope, locals, assign, inputs) {
14120               var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs);
14121               return context ? {value: arg} : arg;
14122             };
14123           },
14124           'binary===': function(left, right, context) {
14125             return function(scope, locals, assign, inputs) {
14126               var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs);
14127               return context ? {value: arg} : arg;
14128             };
14129           },
14130           'binary!==': function(left, right, context) {
14131             return function(scope, locals, assign, inputs) {
14132               var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs);
14133               return context ? {value: arg} : arg;
14134             };
14135           },
14136           'binary==': function(left, right, context) {
14137             return function(scope, locals, assign, inputs) {
14138               var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs);
14139               return context ? {value: arg} : arg;
14140             };
14141           },
14142           'binary!=': function(left, right, context) {
14143             return function(scope, locals, assign, inputs) {
14144               var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs);
14145               return context ? {value: arg} : arg;
14146             };
14147           },
14148           'binary<': function(left, right, context) {
14149             return function(scope, locals, assign, inputs) {
14150               var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs);
14151               return context ? {value: arg} : arg;
14152             };
14153           },
14154           'binary>': function(left, right, context) {
14155             return function(scope, locals, assign, inputs) {
14156               var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs);
14157               return context ? {value: arg} : arg;
14158             };
14159           },
14160           'binary<=': function(left, right, context) {
14161             return function(scope, locals, assign, inputs) {
14162               var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs);
14163               return context ? {value: arg} : arg;
14164             };
14165           },
14166           'binary>=': function(left, right, context) {
14167             return function(scope, locals, assign, inputs) {
14168               var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs);
14169               return context ? {value: arg} : arg;
14170             };
14171           },
14172           'binary&&': function(left, right, context) {
14173             return function(scope, locals, assign, inputs) {
14174               var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs);
14175               return context ? {value: arg} : arg;
14176             };
14177           },
14178           'binary||': function(left, right, context) {
14179             return function(scope, locals, assign, inputs) {
14180               var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs);
14181               return context ? {value: arg} : arg;
14182             };
14183           },
14184           'ternary?:': function(test, alternate, consequent, context) {
14185             return function(scope, locals, assign, inputs) {
14186               var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs);
14187               return context ? {value: arg} : arg;
14188             };
14189           },
14190           value: function(value, context) {
14191             return function() { return context ? {context: undefined, name: undefined, value: value} : value; };
14192           },
14193           identifier: function(name, expensiveChecks, context, create, expression) {
14194             return function(scope, locals, assign, inputs) {
14195               var base = locals && (name in locals) ? locals : scope;
14196               if (create && create !== 1 && base && !(base[name])) {
14197                 base[name] = {};
14198               }
14199               var value = base ? base[name] : undefined;
14200               if (expensiveChecks) {
14201                 ensureSafeObject(value, expression);
14202               }
14203               if (context) {
14204                 return {context: base, name: name, value: value};
14205               } else {
14206                 return value;
14207               }
14208             };
14209           },
14210           computedMember: function(left, right, context, create, expression) {
14211             return function(scope, locals, assign, inputs) {
14212               var lhs = left(scope, locals, assign, inputs);
14213               var rhs;
14214               var value;
14215               if (lhs != null) {
14216                 rhs = right(scope, locals, assign, inputs);
14217                 rhs = getStringValue(rhs);
14218                 ensureSafeMemberName(rhs, expression);
14219                 if (create && create !== 1 && lhs && !(lhs[rhs])) {
14220                   lhs[rhs] = {};
14221                 }
14222                 value = lhs[rhs];
14223                 ensureSafeObject(value, expression);
14224               }
14225               if (context) {
14226                 return {context: lhs, name: rhs, value: value};
14227               } else {
14228                 return value;
14229               }
14230             };
14231           },
14232           nonComputedMember: function(left, right, expensiveChecks, context, create, expression) {
14233             return function(scope, locals, assign, inputs) {
14234               var lhs = left(scope, locals, assign, inputs);
14235               if (create && create !== 1 && lhs && !(lhs[right])) {
14236                 lhs[right] = {};
14237               }
14238               var value = lhs != null ? lhs[right] : undefined;
14239               if (expensiveChecks || isPossiblyDangerousMemberName(right)) {
14240                 ensureSafeObject(value, expression);
14241               }
14242               if (context) {
14243                 return {context: lhs, name: right, value: value};
14244               } else {
14245                 return value;
14246               }
14247             };
14248           },
14249           inputs: function(input, watchId) {
14250             return function(scope, value, locals, inputs) {
14251               if (inputs) return inputs[watchId];
14252               return input(scope, value, locals);
14253             };
14254           }
14255         };
14256
14257         /**
14258          * @constructor
14259          */
14260         var Parser = function(lexer, $filter, options) {
14261           this.lexer = lexer;
14262           this.$filter = $filter;
14263           this.options = options;
14264           this.ast = new AST(this.lexer);
14265           this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) :
14266                                            new ASTCompiler(this.ast, $filter);
14267         };
14268
14269         Parser.prototype = {
14270           constructor: Parser,
14271
14272           parse: function(text) {
14273             return this.astCompiler.compile(text, this.options.expensiveChecks);
14274           }
14275         };
14276
14277         var getterFnCacheDefault = createMap();
14278         var getterFnCacheExpensive = createMap();
14279
14280         function isPossiblyDangerousMemberName(name) {
14281           return name == 'constructor';
14282         }
14283
14284         var objectValueOf = Object.prototype.valueOf;
14285
14286         function getValueOf(value) {
14287           return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
14288         }
14289
14290         ///////////////////////////////////
14291
14292         /**
14293          * @ngdoc service
14294          * @name $parse
14295          * @kind function
14296          *
14297          * @description
14298          *
14299          * Converts Angular {@link guide/expression expression} into a function.
14300          *
14301          * ```js
14302          *   var getter = $parse('user.name');
14303          *   var setter = getter.assign;
14304          *   var context = {user:{name:'angular'}};
14305          *   var locals = {user:{name:'local'}};
14306          *
14307          *   expect(getter(context)).toEqual('angular');
14308          *   setter(context, 'newValue');
14309          *   expect(context.user.name).toEqual('newValue');
14310          *   expect(getter(context, locals)).toEqual('local');
14311          * ```
14312          *
14313          *
14314          * @param {string} expression String expression to compile.
14315          * @returns {function(context, locals)} a function which represents the compiled expression:
14316          *
14317          *    * `context` – `{object}` – an object against which any expressions embedded in the strings
14318          *      are evaluated against (typically a scope object).
14319          *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
14320          *      `context`.
14321          *
14322          *    The returned function also has the following properties:
14323          *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
14324          *        literal.
14325          *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
14326          *        constant literals.
14327          *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
14328          *        set to a function to change its value on the given context.
14329          *
14330          */
14331
14332
14333         /**
14334          * @ngdoc provider
14335          * @name $parseProvider
14336          *
14337          * @description
14338          * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
14339          *  service.
14340          */
14341         function $ParseProvider() {
14342           var cacheDefault = createMap();
14343           var cacheExpensive = createMap();
14344
14345           this.$get = ['$filter', function($filter) {
14346             var noUnsafeEval = csp().noUnsafeEval;
14347             var $parseOptions = {
14348                   csp: noUnsafeEval,
14349                   expensiveChecks: false
14350                 },
14351                 $parseOptionsExpensive = {
14352                   csp: noUnsafeEval,
14353                   expensiveChecks: true
14354                 };
14355
14356             return function $parse(exp, interceptorFn, expensiveChecks) {
14357               var parsedExpression, oneTime, cacheKey;
14358
14359               switch (typeof exp) {
14360                 case 'string':
14361                   exp = exp.trim();
14362                   cacheKey = exp;
14363
14364                   var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
14365                   parsedExpression = cache[cacheKey];
14366
14367                   if (!parsedExpression) {
14368                     if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
14369                       oneTime = true;
14370                       exp = exp.substring(2);
14371                     }
14372                     var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
14373                     var lexer = new Lexer(parseOptions);
14374                     var parser = new Parser(lexer, $filter, parseOptions);
14375                     parsedExpression = parser.parse(exp);
14376                     if (parsedExpression.constant) {
14377                       parsedExpression.$$watchDelegate = constantWatchDelegate;
14378                     } else if (oneTime) {
14379                       parsedExpression.$$watchDelegate = parsedExpression.literal ?
14380                           oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
14381                     } else if (parsedExpression.inputs) {
14382                       parsedExpression.$$watchDelegate = inputsWatchDelegate;
14383                     }
14384                     cache[cacheKey] = parsedExpression;
14385                   }
14386                   return addInterceptor(parsedExpression, interceptorFn);
14387
14388                 case 'function':
14389                   return addInterceptor(exp, interceptorFn);
14390
14391                 default:
14392                   return noop;
14393               }
14394             };
14395
14396             function expressionInputDirtyCheck(newValue, oldValueOfValue) {
14397
14398               if (newValue == null || oldValueOfValue == null) { // null/undefined
14399                 return newValue === oldValueOfValue;
14400               }
14401
14402               if (typeof newValue === 'object') {
14403
14404                 // attempt to convert the value to a primitive type
14405                 // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
14406                 //             be cheaply dirty-checked
14407                 newValue = getValueOf(newValue);
14408
14409                 if (typeof newValue === 'object') {
14410                   // objects/arrays are not supported - deep-watching them would be too expensive
14411                   return false;
14412                 }
14413
14414                 // fall-through to the primitive equality check
14415               }
14416
14417               //Primitive or NaN
14418               return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
14419             }
14420
14421             function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
14422               var inputExpressions = parsedExpression.inputs;
14423               var lastResult;
14424
14425               if (inputExpressions.length === 1) {
14426                 var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
14427                 inputExpressions = inputExpressions[0];
14428                 return scope.$watch(function expressionInputWatch(scope) {
14429                   var newInputValue = inputExpressions(scope);
14430                   if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) {
14431                     lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
14432                     oldInputValueOf = newInputValue && getValueOf(newInputValue);
14433                   }
14434                   return lastResult;
14435                 }, listener, objectEquality, prettyPrintExpression);
14436               }
14437
14438               var oldInputValueOfValues = [];
14439               var oldInputValues = [];
14440               for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
14441                 oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
14442                 oldInputValues[i] = null;
14443               }
14444
14445               return scope.$watch(function expressionInputsWatch(scope) {
14446                 var changed = false;
14447
14448                 for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
14449                   var newInputValue = inputExpressions[i](scope);
14450                   if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
14451                     oldInputValues[i] = newInputValue;
14452                     oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
14453                   }
14454                 }
14455
14456                 if (changed) {
14457                   lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);
14458                 }
14459
14460                 return lastResult;
14461               }, listener, objectEquality, prettyPrintExpression);
14462             }
14463
14464             function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
14465               var unwatch, lastValue;
14466               return unwatch = scope.$watch(function oneTimeWatch(scope) {
14467                 return parsedExpression(scope);
14468               }, function oneTimeListener(value, old, scope) {
14469                 lastValue = value;
14470                 if (isFunction(listener)) {
14471                   listener.apply(this, arguments);
14472                 }
14473                 if (isDefined(value)) {
14474                   scope.$$postDigest(function() {
14475                     if (isDefined(lastValue)) {
14476                       unwatch();
14477                     }
14478                   });
14479                 }
14480               }, objectEquality);
14481             }
14482
14483             function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
14484               var unwatch, lastValue;
14485               return unwatch = scope.$watch(function oneTimeWatch(scope) {
14486                 return parsedExpression(scope);
14487               }, function oneTimeListener(value, old, scope) {
14488                 lastValue = value;
14489                 if (isFunction(listener)) {
14490                   listener.call(this, value, old, scope);
14491                 }
14492                 if (isAllDefined(value)) {
14493                   scope.$$postDigest(function() {
14494                     if (isAllDefined(lastValue)) unwatch();
14495                   });
14496                 }
14497               }, objectEquality);
14498
14499               function isAllDefined(value) {
14500                 var allDefined = true;
14501                 forEach(value, function(val) {
14502                   if (!isDefined(val)) allDefined = false;
14503                 });
14504                 return allDefined;
14505               }
14506             }
14507
14508             function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
14509               var unwatch;
14510               return unwatch = scope.$watch(function constantWatch(scope) {
14511                 return parsedExpression(scope);
14512               }, function constantListener(value, old, scope) {
14513                 if (isFunction(listener)) {
14514                   listener.apply(this, arguments);
14515                 }
14516                 unwatch();
14517               }, objectEquality);
14518             }
14519
14520             function addInterceptor(parsedExpression, interceptorFn) {
14521               if (!interceptorFn) return parsedExpression;
14522               var watchDelegate = parsedExpression.$$watchDelegate;
14523               var useInputs = false;
14524
14525               var regularWatch =
14526                   watchDelegate !== oneTimeLiteralWatchDelegate &&
14527                   watchDelegate !== oneTimeWatchDelegate;
14528
14529               var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {
14530                 var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
14531                 return interceptorFn(value, scope, locals);
14532               } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {
14533                 var value = parsedExpression(scope, locals, assign, inputs);
14534                 var result = interceptorFn(value, scope, locals);
14535                 // we only return the interceptor's result if the
14536                 // initial value is defined (for bind-once)
14537                 return isDefined(value) ? result : value;
14538               };
14539
14540               // Propagate $$watchDelegates other then inputsWatchDelegate
14541               if (parsedExpression.$$watchDelegate &&
14542                   parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
14543                 fn.$$watchDelegate = parsedExpression.$$watchDelegate;
14544               } else if (!interceptorFn.$stateful) {
14545                 // If there is an interceptor, but no watchDelegate then treat the interceptor like
14546                 // we treat filters - it is assumed to be a pure function unless flagged with $stateful
14547                 fn.$$watchDelegate = inputsWatchDelegate;
14548                 useInputs = !parsedExpression.inputs;
14549                 fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
14550               }
14551
14552               return fn;
14553             }
14554           }];
14555         }
14556
14557         /**
14558          * @ngdoc service
14559          * @name $q
14560          * @requires $rootScope
14561          *
14562          * @description
14563          * A service that helps you run functions asynchronously, and use their return values (or exceptions)
14564          * when they are done processing.
14565          *
14566          * This is an implementation of promises/deferred objects inspired by
14567          * [Kris Kowal's Q](https://github.com/kriskowal/q).
14568          *
14569          * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
14570          * implementations, and the other which resembles ES6 promises to some degree.
14571          *
14572          * # $q constructor
14573          *
14574          * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`
14575          * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,
14576          * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
14577          *
14578          * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are
14579          * available yet.
14580          *
14581          * It can be used like so:
14582          *
14583          * ```js
14584          *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`
14585          *   // are available in the current lexical scope (they could have been injected or passed in).
14586          *
14587          *   function asyncGreet(name) {
14588          *     // perform some asynchronous operation, resolve or reject the promise when appropriate.
14589          *     return $q(function(resolve, reject) {
14590          *       setTimeout(function() {
14591          *         if (okToGreet(name)) {
14592          *           resolve('Hello, ' + name + '!');
14593          *         } else {
14594          *           reject('Greeting ' + name + ' is not allowed.');
14595          *         }
14596          *       }, 1000);
14597          *     });
14598          *   }
14599          *
14600          *   var promise = asyncGreet('Robin Hood');
14601          *   promise.then(function(greeting) {
14602          *     alert('Success: ' + greeting);
14603          *   }, function(reason) {
14604          *     alert('Failed: ' + reason);
14605          *   });
14606          * ```
14607          *
14608          * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
14609          *
14610          * Note: unlike ES6 behaviour, an exception thrown in the constructor function will NOT implicitly reject the promise.
14611          *
14612          * However, the more traditional CommonJS-style usage is still available, and documented below.
14613          *
14614          * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
14615          * interface for interacting with an object that represents the result of an action that is
14616          * performed asynchronously, and may or may not be finished at any given point in time.
14617          *
14618          * From the perspective of dealing with error handling, deferred and promise APIs are to
14619          * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
14620          *
14621          * ```js
14622          *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`
14623          *   // are available in the current lexical scope (they could have been injected or passed in).
14624          *
14625          *   function asyncGreet(name) {
14626          *     var deferred = $q.defer();
14627          *
14628          *     setTimeout(function() {
14629          *       deferred.notify('About to greet ' + name + '.');
14630          *
14631          *       if (okToGreet(name)) {
14632          *         deferred.resolve('Hello, ' + name + '!');
14633          *       } else {
14634          *         deferred.reject('Greeting ' + name + ' is not allowed.');
14635          *       }
14636          *     }, 1000);
14637          *
14638          *     return deferred.promise;
14639          *   }
14640          *
14641          *   var promise = asyncGreet('Robin Hood');
14642          *   promise.then(function(greeting) {
14643          *     alert('Success: ' + greeting);
14644          *   }, function(reason) {
14645          *     alert('Failed: ' + reason);
14646          *   }, function(update) {
14647          *     alert('Got notification: ' + update);
14648          *   });
14649          * ```
14650          *
14651          * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
14652          * comes in the way of guarantees that promise and deferred APIs make, see
14653          * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
14654          *
14655          * Additionally the promise api allows for composition that is very hard to do with the
14656          * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
14657          * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
14658          * section on serial or parallel joining of promises.
14659          *
14660          * # The Deferred API
14661          *
14662          * A new instance of deferred is constructed by calling `$q.defer()`.
14663          *
14664          * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
14665          * that can be used for signaling the successful or unsuccessful completion, as well as the status
14666          * of the task.
14667          *
14668          * **Methods**
14669          *
14670          * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
14671          *   constructed via `$q.reject`, the promise will be rejected instead.
14672          * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
14673          *   resolving it with a rejection constructed via `$q.reject`.
14674          * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
14675          *   multiple times before the promise is either resolved or rejected.
14676          *
14677          * **Properties**
14678          *
14679          * - promise – `{Promise}` – promise object associated with this deferred.
14680          *
14681          *
14682          * # The Promise API
14683          *
14684          * A new promise instance is created when a deferred instance is created and can be retrieved by
14685          * calling `deferred.promise`.
14686          *
14687          * The purpose of the promise object is to allow for interested parties to get access to the result
14688          * of the deferred task when it completes.
14689          *
14690          * **Methods**
14691          *
14692          * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
14693          *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
14694          *   as soon as the result is available. The callbacks are called with a single argument: the result
14695          *   or rejection reason. Additionally, the notify callback may be called zero or more times to
14696          *   provide a progress indication, before the promise is resolved or rejected.
14697          *
14698          *   This method *returns a new promise* which is resolved or rejected via the return value of the
14699          *   `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved
14700          *   with the value which is resolved in that promise using
14701          *   [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)).
14702          *   It also notifies via the return value of the `notifyCallback` method. The promise cannot be
14703          *   resolved or rejected from the notifyCallback method.
14704          *
14705          * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
14706          *
14707          * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
14708          *   but to do so without modifying the final value. This is useful to release resources or do some
14709          *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full
14710          *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
14711          *   more information.
14712          *
14713          * # Chaining promises
14714          *
14715          * Because calling the `then` method of a promise returns a new derived promise, it is easily
14716          * possible to create a chain of promises:
14717          *
14718          * ```js
14719          *   promiseB = promiseA.then(function(result) {
14720          *     return result + 1;
14721          *   });
14722          *
14723          *   // promiseB will be resolved immediately after promiseA is resolved and its value
14724          *   // will be the result of promiseA incremented by 1
14725          * ```
14726          *
14727          * It is possible to create chains of any length and since a promise can be resolved with another
14728          * promise (which will defer its resolution further), it is possible to pause/defer resolution of
14729          * the promises at any point in the chain. This makes it possible to implement powerful APIs like
14730          * $http's response interceptors.
14731          *
14732          *
14733          * # Differences between Kris Kowal's Q and $q
14734          *
14735          *  There are two main differences:
14736          *
14737          * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
14738          *   mechanism in angular, which means faster propagation of resolution or rejection into your
14739          *   models and avoiding unnecessary browser repaints, which would result in flickering UI.
14740          * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
14741          *   all the important functionality needed for common async tasks.
14742          *
14743          *  # Testing
14744          *
14745          *  ```js
14746          *    it('should simulate promise', inject(function($q, $rootScope) {
14747          *      var deferred = $q.defer();
14748          *      var promise = deferred.promise;
14749          *      var resolvedValue;
14750          *
14751          *      promise.then(function(value) { resolvedValue = value; });
14752          *      expect(resolvedValue).toBeUndefined();
14753          *
14754          *      // Simulate resolving of promise
14755          *      deferred.resolve(123);
14756          *      // Note that the 'then' function does not get called synchronously.
14757          *      // This is because we want the promise API to always be async, whether or not
14758          *      // it got called synchronously or asynchronously.
14759          *      expect(resolvedValue).toBeUndefined();
14760          *
14761          *      // Propagate promise resolution to 'then' functions using $apply().
14762          *      $rootScope.$apply();
14763          *      expect(resolvedValue).toEqual(123);
14764          *    }));
14765          *  ```
14766          *
14767          * @param {function(function, function)} resolver Function which is responsible for resolving or
14768          *   rejecting the newly created promise. The first parameter is a function which resolves the
14769          *   promise, the second parameter is a function which rejects the promise.
14770          *
14771          * @returns {Promise} The newly created promise.
14772          */
14773         function $QProvider() {
14774
14775           this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
14776             return qFactory(function(callback) {
14777               $rootScope.$evalAsync(callback);
14778             }, $exceptionHandler);
14779           }];
14780         }
14781
14782         function $$QProvider() {
14783           this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
14784             return qFactory(function(callback) {
14785               $browser.defer(callback);
14786             }, $exceptionHandler);
14787           }];
14788         }
14789
14790         /**
14791          * Constructs a promise manager.
14792          *
14793          * @param {function(function)} nextTick Function for executing functions in the next turn.
14794          * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
14795          *     debugging purposes.
14796          * @returns {object} Promise manager.
14797          */
14798         function qFactory(nextTick, exceptionHandler) {
14799           var $qMinErr = minErr('$q', TypeError);
14800           function callOnce(self, resolveFn, rejectFn) {
14801             var called = false;
14802             function wrap(fn) {
14803               return function(value) {
14804                 if (called) return;
14805                 called = true;
14806                 fn.call(self, value);
14807               };
14808             }
14809
14810             return [wrap(resolveFn), wrap(rejectFn)];
14811           }
14812
14813           /**
14814            * @ngdoc method
14815            * @name ng.$q#defer
14816            * @kind function
14817            *
14818            * @description
14819            * Creates a `Deferred` object which represents a task which will finish in the future.
14820            *
14821            * @returns {Deferred} Returns a new instance of deferred.
14822            */
14823           var defer = function() {
14824             return new Deferred();
14825           };
14826
14827           function Promise() {
14828             this.$$state = { status: 0 };
14829           }
14830
14831           extend(Promise.prototype, {
14832             then: function(onFulfilled, onRejected, progressBack) {
14833               if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
14834                 return this;
14835               }
14836               var result = new Deferred();
14837
14838               this.$$state.pending = this.$$state.pending || [];
14839               this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
14840               if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
14841
14842               return result.promise;
14843             },
14844
14845             "catch": function(callback) {
14846               return this.then(null, callback);
14847             },
14848
14849             "finally": function(callback, progressBack) {
14850               return this.then(function(value) {
14851                 return handleCallback(value, true, callback);
14852               }, function(error) {
14853                 return handleCallback(error, false, callback);
14854               }, progressBack);
14855             }
14856           });
14857
14858           //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
14859           function simpleBind(context, fn) {
14860             return function(value) {
14861               fn.call(context, value);
14862             };
14863           }
14864
14865           function processQueue(state) {
14866             var fn, deferred, pending;
14867
14868             pending = state.pending;
14869             state.processScheduled = false;
14870             state.pending = undefined;
14871             for (var i = 0, ii = pending.length; i < ii; ++i) {
14872               deferred = pending[i][0];
14873               fn = pending[i][state.status];
14874               try {
14875                 if (isFunction(fn)) {
14876                   deferred.resolve(fn(state.value));
14877                 } else if (state.status === 1) {
14878                   deferred.resolve(state.value);
14879                 } else {
14880                   deferred.reject(state.value);
14881                 }
14882               } catch (e) {
14883                 deferred.reject(e);
14884                 exceptionHandler(e);
14885               }
14886             }
14887           }
14888
14889           function scheduleProcessQueue(state) {
14890             if (state.processScheduled || !state.pending) return;
14891             state.processScheduled = true;
14892             nextTick(function() { processQueue(state); });
14893           }
14894
14895           function Deferred() {
14896             this.promise = new Promise();
14897             //Necessary to support unbound execution :/
14898             this.resolve = simpleBind(this, this.resolve);
14899             this.reject = simpleBind(this, this.reject);
14900             this.notify = simpleBind(this, this.notify);
14901           }
14902
14903           extend(Deferred.prototype, {
14904             resolve: function(val) {
14905               if (this.promise.$$state.status) return;
14906               if (val === this.promise) {
14907                 this.$$reject($qMinErr(
14908                   'qcycle',
14909                   "Expected promise to be resolved with value other than itself '{0}'",
14910                   val));
14911               } else {
14912                 this.$$resolve(val);
14913               }
14914
14915             },
14916
14917             $$resolve: function(val) {
14918               var then, fns;
14919
14920               fns = callOnce(this, this.$$resolve, this.$$reject);
14921               try {
14922                 if ((isObject(val) || isFunction(val))) then = val && val.then;
14923                 if (isFunction(then)) {
14924                   this.promise.$$state.status = -1;
14925                   then.call(val, fns[0], fns[1], this.notify);
14926                 } else {
14927                   this.promise.$$state.value = val;
14928                   this.promise.$$state.status = 1;
14929                   scheduleProcessQueue(this.promise.$$state);
14930                 }
14931               } catch (e) {
14932                 fns[1](e);
14933                 exceptionHandler(e);
14934               }
14935             },
14936
14937             reject: function(reason) {
14938               if (this.promise.$$state.status) return;
14939               this.$$reject(reason);
14940             },
14941
14942             $$reject: function(reason) {
14943               this.promise.$$state.value = reason;
14944               this.promise.$$state.status = 2;
14945               scheduleProcessQueue(this.promise.$$state);
14946             },
14947
14948             notify: function(progress) {
14949               var callbacks = this.promise.$$state.pending;
14950
14951               if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {
14952                 nextTick(function() {
14953                   var callback, result;
14954                   for (var i = 0, ii = callbacks.length; i < ii; i++) {
14955                     result = callbacks[i][0];
14956                     callback = callbacks[i][3];
14957                     try {
14958                       result.notify(isFunction(callback) ? callback(progress) : progress);
14959                     } catch (e) {
14960                       exceptionHandler(e);
14961                     }
14962                   }
14963                 });
14964               }
14965             }
14966           });
14967
14968           /**
14969            * @ngdoc method
14970            * @name $q#reject
14971            * @kind function
14972            *
14973            * @description
14974            * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
14975            * used to forward rejection in a chain of promises. If you are dealing with the last promise in
14976            * a promise chain, you don't need to worry about it.
14977            *
14978            * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
14979            * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
14980            * a promise error callback and you want to forward the error to the promise derived from the
14981            * current promise, you have to "rethrow" the error by returning a rejection constructed via
14982            * `reject`.
14983            *
14984            * ```js
14985            *   promiseB = promiseA.then(function(result) {
14986            *     // success: do something and resolve promiseB
14987            *     //          with the old or a new result
14988            *     return result;
14989            *   }, function(reason) {
14990            *     // error: handle the error if possible and
14991            *     //        resolve promiseB with newPromiseOrValue,
14992            *     //        otherwise forward the rejection to promiseB
14993            *     if (canHandle(reason)) {
14994            *      // handle the error and recover
14995            *      return newPromiseOrValue;
14996            *     }
14997            *     return $q.reject(reason);
14998            *   });
14999            * ```
15000            *
15001            * @param {*} reason Constant, message, exception or an object representing the rejection reason.
15002            * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
15003            */
15004           var reject = function(reason) {
15005             var result = new Deferred();
15006             result.reject(reason);
15007             return result.promise;
15008           };
15009
15010           var makePromise = function makePromise(value, resolved) {
15011             var result = new Deferred();
15012             if (resolved) {
15013               result.resolve(value);
15014             } else {
15015               result.reject(value);
15016             }
15017             return result.promise;
15018           };
15019
15020           var handleCallback = function handleCallback(value, isResolved, callback) {
15021             var callbackOutput = null;
15022             try {
15023               if (isFunction(callback)) callbackOutput = callback();
15024             } catch (e) {
15025               return makePromise(e, false);
15026             }
15027             if (isPromiseLike(callbackOutput)) {
15028               return callbackOutput.then(function() {
15029                 return makePromise(value, isResolved);
15030               }, function(error) {
15031                 return makePromise(error, false);
15032               });
15033             } else {
15034               return makePromise(value, isResolved);
15035             }
15036           };
15037
15038           /**
15039            * @ngdoc method
15040            * @name $q#when
15041            * @kind function
15042            *
15043            * @description
15044            * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
15045            * This is useful when you are dealing with an object that might or might not be a promise, or if
15046            * the promise comes from a source that can't be trusted.
15047            *
15048            * @param {*} value Value or a promise
15049            * @param {Function=} successCallback
15050            * @param {Function=} errorCallback
15051            * @param {Function=} progressCallback
15052            * @returns {Promise} Returns a promise of the passed value or promise
15053            */
15054
15055
15056           var when = function(value, callback, errback, progressBack) {
15057             var result = new Deferred();
15058             result.resolve(value);
15059             return result.promise.then(callback, errback, progressBack);
15060           };
15061
15062           /**
15063            * @ngdoc method
15064            * @name $q#resolve
15065            * @kind function
15066            *
15067            * @description
15068            * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.
15069            *
15070            * @param {*} value Value or a promise
15071            * @param {Function=} successCallback
15072            * @param {Function=} errorCallback
15073            * @param {Function=} progressCallback
15074            * @returns {Promise} Returns a promise of the passed value or promise
15075            */
15076           var resolve = when;
15077
15078           /**
15079            * @ngdoc method
15080            * @name $q#all
15081            * @kind function
15082            *
15083            * @description
15084            * Combines multiple promises into a single promise that is resolved when all of the input
15085            * promises are resolved.
15086            *
15087            * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
15088            * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
15089            *   each value corresponding to the promise at the same index/key in the `promises` array/hash.
15090            *   If any of the promises is resolved with a rejection, this resulting promise will be rejected
15091            *   with the same rejection value.
15092            */
15093
15094           function all(promises) {
15095             var deferred = new Deferred(),
15096                 counter = 0,
15097                 results = isArray(promises) ? [] : {};
15098
15099             forEach(promises, function(promise, key) {
15100               counter++;
15101               when(promise).then(function(value) {
15102                 if (results.hasOwnProperty(key)) return;
15103                 results[key] = value;
15104                 if (!(--counter)) deferred.resolve(results);
15105               }, function(reason) {
15106                 if (results.hasOwnProperty(key)) return;
15107                 deferred.reject(reason);
15108               });
15109             });
15110
15111             if (counter === 0) {
15112               deferred.resolve(results);
15113             }
15114
15115             return deferred.promise;
15116           }
15117
15118           var $Q = function Q(resolver) {
15119             if (!isFunction(resolver)) {
15120               throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
15121             }
15122
15123             if (!(this instanceof Q)) {
15124               // More useful when $Q is the Promise itself.
15125               return new Q(resolver);
15126             }
15127
15128             var deferred = new Deferred();
15129
15130             function resolveFn(value) {
15131               deferred.resolve(value);
15132             }
15133
15134             function rejectFn(reason) {
15135               deferred.reject(reason);
15136             }
15137
15138             resolver(resolveFn, rejectFn);
15139
15140             return deferred.promise;
15141           };
15142
15143           $Q.defer = defer;
15144           $Q.reject = reject;
15145           $Q.when = when;
15146           $Q.resolve = resolve;
15147           $Q.all = all;
15148
15149           return $Q;
15150         }
15151
15152         function $$RAFProvider() { //rAF
15153           this.$get = ['$window', '$timeout', function($window, $timeout) {
15154             var requestAnimationFrame = $window.requestAnimationFrame ||
15155                                         $window.webkitRequestAnimationFrame;
15156
15157             var cancelAnimationFrame = $window.cancelAnimationFrame ||
15158                                        $window.webkitCancelAnimationFrame ||
15159                                        $window.webkitCancelRequestAnimationFrame;
15160
15161             var rafSupported = !!requestAnimationFrame;
15162             var raf = rafSupported
15163               ? function(fn) {
15164                   var id = requestAnimationFrame(fn);
15165                   return function() {
15166                     cancelAnimationFrame(id);
15167                   };
15168                 }
15169               : function(fn) {
15170                   var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
15171                   return function() {
15172                     $timeout.cancel(timer);
15173                   };
15174                 };
15175
15176             raf.supported = rafSupported;
15177
15178             return raf;
15179           }];
15180         }
15181
15182         /**
15183          * DESIGN NOTES
15184          *
15185          * The design decisions behind the scope are heavily favored for speed and memory consumption.
15186          *
15187          * The typical use of scope is to watch the expressions, which most of the time return the same
15188          * value as last time so we optimize the operation.
15189          *
15190          * Closures construction is expensive in terms of speed as well as memory:
15191          *   - No closures, instead use prototypical inheritance for API
15192          *   - Internal state needs to be stored on scope directly, which means that private state is
15193          *     exposed as $$____ properties
15194          *
15195          * Loop operations are optimized by using while(count--) { ... }
15196          *   - This means that in order to keep the same order of execution as addition we have to add
15197          *     items to the array at the beginning (unshift) instead of at the end (push)
15198          *
15199          * Child scopes are created and removed often
15200          *   - Using an array would be slow since inserts in the middle are expensive; so we use linked lists
15201          *
15202          * There are fewer watches than observers. This is why you don't want the observer to be implemented
15203          * in the same way as watch. Watch requires return of the initialization function which is expensive
15204          * to construct.
15205          */
15206
15207
15208         /**
15209          * @ngdoc provider
15210          * @name $rootScopeProvider
15211          * @description
15212          *
15213          * Provider for the $rootScope service.
15214          */
15215
15216         /**
15217          * @ngdoc method
15218          * @name $rootScopeProvider#digestTtl
15219          * @description
15220          *
15221          * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
15222          * assuming that the model is unstable.
15223          *
15224          * The current default is 10 iterations.
15225          *
15226          * In complex applications it's possible that the dependencies between `$watch`s will result in
15227          * several digest iterations. However if an application needs more than the default 10 digest
15228          * iterations for its model to stabilize then you should investigate what is causing the model to
15229          * continuously change during the digest.
15230          *
15231          * Increasing the TTL could have performance implications, so you should not change it without
15232          * proper justification.
15233          *
15234          * @param {number} limit The number of digest iterations.
15235          */
15236
15237
15238         /**
15239          * @ngdoc service
15240          * @name $rootScope
15241          * @description
15242          *
15243          * Every application has a single root {@link ng.$rootScope.Scope scope}.
15244          * All other scopes are descendant scopes of the root scope. Scopes provide separation
15245          * between the model and the view, via a mechanism for watching the model for changes.
15246          * They also provide event emission/broadcast and subscription facility. See the
15247          * {@link guide/scope developer guide on scopes}.
15248          */
15249         function $RootScopeProvider() {
15250           var TTL = 10;
15251           var $rootScopeMinErr = minErr('$rootScope');
15252           var lastDirtyWatch = null;
15253           var applyAsyncId = null;
15254
15255           this.digestTtl = function(value) {
15256             if (arguments.length) {
15257               TTL = value;
15258             }
15259             return TTL;
15260           };
15261
15262           function createChildScopeClass(parent) {
15263             function ChildScope() {
15264               this.$$watchers = this.$$nextSibling =
15265                   this.$$childHead = this.$$childTail = null;
15266               this.$$listeners = {};
15267               this.$$listenerCount = {};
15268               this.$$watchersCount = 0;
15269               this.$id = nextUid();
15270               this.$$ChildScope = null;
15271             }
15272             ChildScope.prototype = parent;
15273             return ChildScope;
15274           }
15275
15276           this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
15277               function($injector, $exceptionHandler, $parse, $browser) {
15278
15279             function destroyChildScope($event) {
15280                 $event.currentScope.$$destroyed = true;
15281             }
15282
15283             function cleanUpScope($scope) {
15284
15285               if (msie === 9) {
15286                 // There is a memory leak in IE9 if all child scopes are not disconnected
15287                 // completely when a scope is destroyed. So this code will recurse up through
15288                 // all this scopes children
15289                 //
15290                 // See issue https://github.com/angular/angular.js/issues/10706
15291                 $scope.$$childHead && cleanUpScope($scope.$$childHead);
15292                 $scope.$$nextSibling && cleanUpScope($scope.$$nextSibling);
15293               }
15294
15295               // The code below works around IE9 and V8's memory leaks
15296               //
15297               // See:
15298               // - https://code.google.com/p/v8/issues/detail?id=2073#c26
15299               // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
15300               // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
15301
15302               $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =
15303                   $scope.$$childTail = $scope.$root = $scope.$$watchers = null;
15304             }
15305
15306             /**
15307              * @ngdoc type
15308              * @name $rootScope.Scope
15309              *
15310              * @description
15311              * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
15312              * {@link auto.$injector $injector}. Child scopes are created using the
15313              * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
15314              * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for
15315              * an in-depth introduction and usage examples.
15316              *
15317              *
15318              * # Inheritance
15319              * A scope can inherit from a parent scope, as in this example:
15320              * ```js
15321                  var parent = $rootScope;
15322                  var child = parent.$new();
15323
15324                  parent.salutation = "Hello";
15325                  expect(child.salutation).toEqual('Hello');
15326
15327                  child.salutation = "Welcome";
15328                  expect(child.salutation).toEqual('Welcome');
15329                  expect(parent.salutation).toEqual('Hello');
15330              * ```
15331              *
15332              * When interacting with `Scope` in tests, additional helper methods are available on the
15333              * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional
15334              * details.
15335              *
15336              *
15337              * @param {Object.<string, function()>=} providers Map of service factory which need to be
15338              *                                       provided for the current scope. Defaults to {@link ng}.
15339              * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
15340              *                              append/override services provided by `providers`. This is handy
15341              *                              when unit-testing and having the need to override a default
15342              *                              service.
15343              * @returns {Object} Newly created scope.
15344              *
15345              */
15346             function Scope() {
15347               this.$id = nextUid();
15348               this.$$phase = this.$parent = this.$$watchers =
15349                              this.$$nextSibling = this.$$prevSibling =
15350                              this.$$childHead = this.$$childTail = null;
15351               this.$root = this;
15352               this.$$destroyed = false;
15353               this.$$listeners = {};
15354               this.$$listenerCount = {};
15355               this.$$watchersCount = 0;
15356               this.$$isolateBindings = null;
15357             }
15358
15359             /**
15360              * @ngdoc property
15361              * @name $rootScope.Scope#$id
15362              *
15363              * @description
15364              * Unique scope ID (monotonically increasing) useful for debugging.
15365              */
15366
15367              /**
15368               * @ngdoc property
15369               * @name $rootScope.Scope#$parent
15370               *
15371               * @description
15372               * Reference to the parent scope.
15373               */
15374
15375               /**
15376                * @ngdoc property
15377                * @name $rootScope.Scope#$root
15378                *
15379                * @description
15380                * Reference to the root scope.
15381                */
15382
15383             Scope.prototype = {
15384               constructor: Scope,
15385               /**
15386                * @ngdoc method
15387                * @name $rootScope.Scope#$new
15388                * @kind function
15389                *
15390                * @description
15391                * Creates a new child {@link ng.$rootScope.Scope scope}.
15392                *
15393                * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
15394                * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
15395                *
15396                * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
15397                * desired for the scope and its child scopes to be permanently detached from the parent and
15398                * thus stop participating in model change detection and listener notification by invoking.
15399                *
15400                * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
15401                *         parent scope. The scope is isolated, as it can not see parent scope properties.
15402                *         When creating widgets, it is useful for the widget to not accidentally read parent
15403                *         state.
15404                *
15405                * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`
15406                *                              of the newly created scope. Defaults to `this` scope if not provided.
15407                *                              This is used when creating a transclude scope to correctly place it
15408                *                              in the scope hierarchy while maintaining the correct prototypical
15409                *                              inheritance.
15410                *
15411                * @returns {Object} The newly created child scope.
15412                *
15413                */
15414               $new: function(isolate, parent) {
15415                 var child;
15416
15417                 parent = parent || this;
15418
15419                 if (isolate) {
15420                   child = new Scope();
15421                   child.$root = this.$root;
15422                 } else {
15423                   // Only create a child scope class if somebody asks for one,
15424                   // but cache it to allow the VM to optimize lookups.
15425                   if (!this.$$ChildScope) {
15426                     this.$$ChildScope = createChildScopeClass(this);
15427                   }
15428                   child = new this.$$ChildScope();
15429                 }
15430                 child.$parent = parent;
15431                 child.$$prevSibling = parent.$$childTail;
15432                 if (parent.$$childHead) {
15433                   parent.$$childTail.$$nextSibling = child;
15434                   parent.$$childTail = child;
15435                 } else {
15436                   parent.$$childHead = parent.$$childTail = child;
15437                 }
15438
15439                 // When the new scope is not isolated or we inherit from `this`, and
15440                 // the parent scope is destroyed, the property `$$destroyed` is inherited
15441                 // prototypically. In all other cases, this property needs to be set
15442                 // when the parent scope is destroyed.
15443                 // The listener needs to be added after the parent is set
15444                 if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
15445
15446                 return child;
15447               },
15448
15449               /**
15450                * @ngdoc method
15451                * @name $rootScope.Scope#$watch
15452                * @kind function
15453                *
15454                * @description
15455                * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
15456                *
15457                * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
15458                *   $digest()} and should return the value that will be watched. (`watchExpression` should not change
15459                *   its value when executed multiple times with the same input because it may be executed multiple
15460                *   times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be
15461                *   [idempotent](http://en.wikipedia.org/wiki/Idempotence).
15462                * - The `listener` is called only when the value from the current `watchExpression` and the
15463                *   previous call to `watchExpression` are not equal (with the exception of the initial run,
15464                *   see below). Inequality is determined according to reference inequality,
15465                *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
15466                *    via the `!==` Javascript operator, unless `objectEquality == true`
15467                *   (see next point)
15468                * - When `objectEquality == true`, inequality of the `watchExpression` is determined
15469                *   according to the {@link angular.equals} function. To save the value of the object for
15470                *   later comparison, the {@link angular.copy} function is used. This therefore means that
15471                *   watching complex objects will have adverse memory and performance implications.
15472                * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
15473                *   This is achieved by rerunning the watchers until no changes are detected. The rerun
15474                *   iteration limit is 10 to prevent an infinite loop deadlock.
15475                *
15476                *
15477                * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
15478                * you can register a `watchExpression` function with no `listener`. (Be prepared for
15479                * multiple calls to your `watchExpression` because it will execute multiple times in a
15480                * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)
15481                *
15482                * After a watcher is registered with the scope, the `listener` fn is called asynchronously
15483                * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
15484                * watcher. In rare cases, this is undesirable because the listener is called when the result
15485                * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
15486                * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
15487                * listener was called due to initialization.
15488                *
15489                *
15490                *
15491                * # Example
15492                * ```js
15493                    // let's assume that scope was dependency injected as the $rootScope
15494                    var scope = $rootScope;
15495                    scope.name = 'misko';
15496                    scope.counter = 0;
15497
15498                    expect(scope.counter).toEqual(0);
15499                    scope.$watch('name', function(newValue, oldValue) {
15500                      scope.counter = scope.counter + 1;
15501                    });
15502                    expect(scope.counter).toEqual(0);
15503
15504                    scope.$digest();
15505                    // the listener is always called during the first $digest loop after it was registered
15506                    expect(scope.counter).toEqual(1);
15507
15508                    scope.$digest();
15509                    // but now it will not be called unless the value changes
15510                    expect(scope.counter).toEqual(1);
15511
15512                    scope.name = 'adam';
15513                    scope.$digest();
15514                    expect(scope.counter).toEqual(2);
15515
15516
15517
15518                    // Using a function as a watchExpression
15519                    var food;
15520                    scope.foodCounter = 0;
15521                    expect(scope.foodCounter).toEqual(0);
15522                    scope.$watch(
15523                      // This function returns the value being watched. It is called for each turn of the $digest loop
15524                      function() { return food; },
15525                      // This is the change listener, called when the value returned from the above function changes
15526                      function(newValue, oldValue) {
15527                        if ( newValue !== oldValue ) {
15528                          // Only increment the counter if the value changed
15529                          scope.foodCounter = scope.foodCounter + 1;
15530                        }
15531                      }
15532                    );
15533                    // No digest has been run so the counter will be zero
15534                    expect(scope.foodCounter).toEqual(0);
15535
15536                    // Run the digest but since food has not changed count will still be zero
15537                    scope.$digest();
15538                    expect(scope.foodCounter).toEqual(0);
15539
15540                    // Update food and run digest.  Now the counter will increment
15541                    food = 'cheeseburger';
15542                    scope.$digest();
15543                    expect(scope.foodCounter).toEqual(1);
15544
15545                * ```
15546                *
15547                *
15548                *
15549                * @param {(function()|string)} watchExpression Expression that is evaluated on each
15550                *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
15551                *    a call to the `listener`.
15552                *
15553                *    - `string`: Evaluated as {@link guide/expression expression}
15554                *    - `function(scope)`: called with current `scope` as a parameter.
15555                * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value
15556                *    of `watchExpression` changes.
15557                *
15558                *    - `newVal` contains the current value of the `watchExpression`
15559                *    - `oldVal` contains the previous value of the `watchExpression`
15560                *    - `scope` refers to the current scope
15561                * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
15562                *     comparing for reference equality.
15563                * @returns {function()} Returns a deregistration function for this listener.
15564                */
15565               $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) {
15566                 var get = $parse(watchExp);
15567
15568                 if (get.$$watchDelegate) {
15569                   return get.$$watchDelegate(this, listener, objectEquality, get, watchExp);
15570                 }
15571                 var scope = this,
15572                     array = scope.$$watchers,
15573                     watcher = {
15574                       fn: listener,
15575                       last: initWatchVal,
15576                       get: get,
15577                       exp: prettyPrintExpression || watchExp,
15578                       eq: !!objectEquality
15579                     };
15580
15581                 lastDirtyWatch = null;
15582
15583                 if (!isFunction(listener)) {
15584                   watcher.fn = noop;
15585                 }
15586
15587                 if (!array) {
15588                   array = scope.$$watchers = [];
15589                 }
15590                 // we use unshift since we use a while loop in $digest for speed.
15591                 // the while loop reads in reverse order.
15592                 array.unshift(watcher);
15593                 incrementWatchersCount(this, 1);
15594
15595                 return function deregisterWatch() {
15596                   if (arrayRemove(array, watcher) >= 0) {
15597                     incrementWatchersCount(scope, -1);
15598                   }
15599                   lastDirtyWatch = null;
15600                 };
15601               },
15602
15603               /**
15604                * @ngdoc method
15605                * @name $rootScope.Scope#$watchGroup
15606                * @kind function
15607                *
15608                * @description
15609                * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
15610                * If any one expression in the collection changes the `listener` is executed.
15611                *
15612                * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
15613                *   call to $digest() to see if any items changes.
15614                * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
15615                *
15616                * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
15617                * watched using {@link ng.$rootScope.Scope#$watch $watch()}
15618                *
15619                * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
15620                *    expression in `watchExpressions` changes
15621                *    The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
15622                *    those of `watchExpression`
15623                *    and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
15624                *    those of `watchExpression`
15625                *    The `scope` refers to the current scope.
15626                * @returns {function()} Returns a de-registration function for all listeners.
15627                */
15628               $watchGroup: function(watchExpressions, listener) {
15629                 var oldValues = new Array(watchExpressions.length);
15630                 var newValues = new Array(watchExpressions.length);
15631                 var deregisterFns = [];
15632                 var self = this;
15633                 var changeReactionScheduled = false;
15634                 var firstRun = true;
15635
15636                 if (!watchExpressions.length) {
15637                   // No expressions means we call the listener ASAP
15638                   var shouldCall = true;
15639                   self.$evalAsync(function() {
15640                     if (shouldCall) listener(newValues, newValues, self);
15641                   });
15642                   return function deregisterWatchGroup() {
15643                     shouldCall = false;
15644                   };
15645                 }
15646
15647                 if (watchExpressions.length === 1) {
15648                   // Special case size of one
15649                   return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
15650                     newValues[0] = value;
15651                     oldValues[0] = oldValue;
15652                     listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
15653                   });
15654                 }
15655
15656                 forEach(watchExpressions, function(expr, i) {
15657                   var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
15658                     newValues[i] = value;
15659                     oldValues[i] = oldValue;
15660                     if (!changeReactionScheduled) {
15661                       changeReactionScheduled = true;
15662                       self.$evalAsync(watchGroupAction);
15663                     }
15664                   });
15665                   deregisterFns.push(unwatchFn);
15666                 });
15667
15668                 function watchGroupAction() {
15669                   changeReactionScheduled = false;
15670
15671                   if (firstRun) {
15672                     firstRun = false;
15673                     listener(newValues, newValues, self);
15674                   } else {
15675                     listener(newValues, oldValues, self);
15676                   }
15677                 }
15678
15679                 return function deregisterWatchGroup() {
15680                   while (deregisterFns.length) {
15681                     deregisterFns.shift()();
15682                   }
15683                 };
15684               },
15685
15686
15687               /**
15688                * @ngdoc method
15689                * @name $rootScope.Scope#$watchCollection
15690                * @kind function
15691                *
15692                * @description
15693                * Shallow watches the properties of an object and fires whenever any of the properties change
15694                * (for arrays, this implies watching the array items; for object maps, this implies watching
15695                * the properties). If a change is detected, the `listener` callback is fired.
15696                *
15697                * - The `obj` collection is observed via standard $watch operation and is examined on every
15698                *   call to $digest() to see if any items have been added, removed, or moved.
15699                * - The `listener` is called whenever anything within the `obj` has changed. Examples include
15700                *   adding, removing, and moving items belonging to an object or array.
15701                *
15702                *
15703                * # Example
15704                * ```js
15705                   $scope.names = ['igor', 'matias', 'misko', 'james'];
15706                   $scope.dataCount = 4;
15707
15708                   $scope.$watchCollection('names', function(newNames, oldNames) {
15709                     $scope.dataCount = newNames.length;
15710                   });
15711
15712                   expect($scope.dataCount).toEqual(4);
15713                   $scope.$digest();
15714
15715                   //still at 4 ... no changes
15716                   expect($scope.dataCount).toEqual(4);
15717
15718                   $scope.names.pop();
15719                   $scope.$digest();
15720
15721                   //now there's been a change
15722                   expect($scope.dataCount).toEqual(3);
15723                * ```
15724                *
15725                *
15726                * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
15727                *    expression value should evaluate to an object or an array which is observed on each
15728                *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
15729                *    collection will trigger a call to the `listener`.
15730                *
15731                * @param {function(newCollection, oldCollection, scope)} listener a callback function called
15732                *    when a change is detected.
15733                *    - The `newCollection` object is the newly modified data obtained from the `obj` expression
15734                *    - The `oldCollection` object is a copy of the former collection data.
15735                *      Due to performance considerations, the`oldCollection` value is computed only if the
15736                *      `listener` function declares two or more arguments.
15737                *    - The `scope` argument refers to the current scope.
15738                *
15739                * @returns {function()} Returns a de-registration function for this listener. When the
15740                *    de-registration function is executed, the internal watch operation is terminated.
15741                */
15742               $watchCollection: function(obj, listener) {
15743                 $watchCollectionInterceptor.$stateful = true;
15744
15745                 var self = this;
15746                 // the current value, updated on each dirty-check run
15747                 var newValue;
15748                 // a shallow copy of the newValue from the last dirty-check run,
15749                 // updated to match newValue during dirty-check run
15750                 var oldValue;
15751                 // a shallow copy of the newValue from when the last change happened
15752                 var veryOldValue;
15753                 // only track veryOldValue if the listener is asking for it
15754                 var trackVeryOldValue = (listener.length > 1);
15755                 var changeDetected = 0;
15756                 var changeDetector = $parse(obj, $watchCollectionInterceptor);
15757                 var internalArray = [];
15758                 var internalObject = {};
15759                 var initRun = true;
15760                 var oldLength = 0;
15761
15762                 function $watchCollectionInterceptor(_value) {
15763                   newValue = _value;
15764                   var newLength, key, bothNaN, newItem, oldItem;
15765
15766                   // If the new value is undefined, then return undefined as the watch may be a one-time watch
15767                   if (isUndefined(newValue)) return;
15768
15769                   if (!isObject(newValue)) { // if primitive
15770                     if (oldValue !== newValue) {
15771                       oldValue = newValue;
15772                       changeDetected++;
15773                     }
15774                   } else if (isArrayLike(newValue)) {
15775                     if (oldValue !== internalArray) {
15776                       // we are transitioning from something which was not an array into array.
15777                       oldValue = internalArray;
15778                       oldLength = oldValue.length = 0;
15779                       changeDetected++;
15780                     }
15781
15782                     newLength = newValue.length;
15783
15784                     if (oldLength !== newLength) {
15785                       // if lengths do not match we need to trigger change notification
15786                       changeDetected++;
15787                       oldValue.length = oldLength = newLength;
15788                     }
15789                     // copy the items to oldValue and look for changes.
15790                     for (var i = 0; i < newLength; i++) {
15791                       oldItem = oldValue[i];
15792                       newItem = newValue[i];
15793
15794                       bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
15795                       if (!bothNaN && (oldItem !== newItem)) {
15796                         changeDetected++;
15797                         oldValue[i] = newItem;
15798                       }
15799                     }
15800                   } else {
15801                     if (oldValue !== internalObject) {
15802                       // we are transitioning from something which was not an object into object.
15803                       oldValue = internalObject = {};
15804                       oldLength = 0;
15805                       changeDetected++;
15806                     }
15807                     // copy the items to oldValue and look for changes.
15808                     newLength = 0;
15809                     for (key in newValue) {
15810                       if (hasOwnProperty.call(newValue, key)) {
15811                         newLength++;
15812                         newItem = newValue[key];
15813                         oldItem = oldValue[key];
15814
15815                         if (key in oldValue) {
15816                           bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
15817                           if (!bothNaN && (oldItem !== newItem)) {
15818                             changeDetected++;
15819                             oldValue[key] = newItem;
15820                           }
15821                         } else {
15822                           oldLength++;
15823                           oldValue[key] = newItem;
15824                           changeDetected++;
15825                         }
15826                       }
15827                     }
15828                     if (oldLength > newLength) {
15829                       // we used to have more keys, need to find them and destroy them.
15830                       changeDetected++;
15831                       for (key in oldValue) {
15832                         if (!hasOwnProperty.call(newValue, key)) {
15833                           oldLength--;
15834                           delete oldValue[key];
15835                         }
15836                       }
15837                     }
15838                   }
15839                   return changeDetected;
15840                 }
15841
15842                 function $watchCollectionAction() {
15843                   if (initRun) {
15844                     initRun = false;
15845                     listener(newValue, newValue, self);
15846                   } else {
15847                     listener(newValue, veryOldValue, self);
15848                   }
15849
15850                   // make a copy for the next time a collection is changed
15851                   if (trackVeryOldValue) {
15852                     if (!isObject(newValue)) {
15853                       //primitive
15854                       veryOldValue = newValue;
15855                     } else if (isArrayLike(newValue)) {
15856                       veryOldValue = new Array(newValue.length);
15857                       for (var i = 0; i < newValue.length; i++) {
15858                         veryOldValue[i] = newValue[i];
15859                       }
15860                     } else { // if object
15861                       veryOldValue = {};
15862                       for (var key in newValue) {
15863                         if (hasOwnProperty.call(newValue, key)) {
15864                           veryOldValue[key] = newValue[key];
15865                         }
15866                       }
15867                     }
15868                   }
15869                 }
15870
15871                 return this.$watch(changeDetector, $watchCollectionAction);
15872               },
15873
15874               /**
15875                * @ngdoc method
15876                * @name $rootScope.Scope#$digest
15877                * @kind function
15878                *
15879                * @description
15880                * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
15881                * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
15882                * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
15883                * until no more listeners are firing. This means that it is possible to get into an infinite
15884                * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
15885                * iterations exceeds 10.
15886                *
15887                * Usually, you don't call `$digest()` directly in
15888                * {@link ng.directive:ngController controllers} or in
15889                * {@link ng.$compileProvider#directive directives}.
15890                * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
15891                * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.
15892                *
15893                * If you want to be notified whenever `$digest()` is called,
15894                * you can register a `watchExpression` function with
15895                * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
15896                *
15897                * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
15898                *
15899                * # Example
15900                * ```js
15901                    var scope = ...;
15902                    scope.name = 'misko';
15903                    scope.counter = 0;
15904
15905                    expect(scope.counter).toEqual(0);
15906                    scope.$watch('name', function(newValue, oldValue) {
15907                      scope.counter = scope.counter + 1;
15908                    });
15909                    expect(scope.counter).toEqual(0);
15910
15911                    scope.$digest();
15912                    // the listener is always called during the first $digest loop after it was registered
15913                    expect(scope.counter).toEqual(1);
15914
15915                    scope.$digest();
15916                    // but now it will not be called unless the value changes
15917                    expect(scope.counter).toEqual(1);
15918
15919                    scope.name = 'adam';
15920                    scope.$digest();
15921                    expect(scope.counter).toEqual(2);
15922                * ```
15923                *
15924                */
15925               $digest: function() {
15926                 var watch, value, last,
15927                     watchers,
15928                     length,
15929                     dirty, ttl = TTL,
15930                     next, current, target = this,
15931                     watchLog = [],
15932                     logIdx, logMsg, asyncTask;
15933
15934                 beginPhase('$digest');
15935                 // Check for changes to browser url that happened in sync before the call to $digest
15936                 $browser.$$checkUrlChange();
15937
15938                 if (this === $rootScope && applyAsyncId !== null) {
15939                   // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then
15940                   // cancel the scheduled $apply and flush the queue of expressions to be evaluated.
15941                   $browser.defer.cancel(applyAsyncId);
15942                   flushApplyAsync();
15943                 }
15944
15945                 lastDirtyWatch = null;
15946
15947                 do { // "while dirty" loop
15948                   dirty = false;
15949                   current = target;
15950
15951                   while (asyncQueue.length) {
15952                     try {
15953                       asyncTask = asyncQueue.shift();
15954                       asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
15955                     } catch (e) {
15956                       $exceptionHandler(e);
15957                     }
15958                     lastDirtyWatch = null;
15959                   }
15960
15961                   traverseScopesLoop:
15962                   do { // "traverse the scopes" loop
15963                     if ((watchers = current.$$watchers)) {
15964                       // process our watches
15965                       length = watchers.length;
15966                       while (length--) {
15967                         try {
15968                           watch = watchers[length];
15969                           // Most common watches are on primitives, in which case we can short
15970                           // circuit it with === operator, only when === fails do we use .equals
15971                           if (watch) {
15972                             if ((value = watch.get(current)) !== (last = watch.last) &&
15973                                 !(watch.eq
15974                                     ? equals(value, last)
15975                                     : (typeof value === 'number' && typeof last === 'number'
15976                                        && isNaN(value) && isNaN(last)))) {
15977                               dirty = true;
15978                               lastDirtyWatch = watch;
15979                               watch.last = watch.eq ? copy(value, null) : value;
15980                               watch.fn(value, ((last === initWatchVal) ? value : last), current);
15981                               if (ttl < 5) {
15982                                 logIdx = 4 - ttl;
15983                                 if (!watchLog[logIdx]) watchLog[logIdx] = [];
15984                                 watchLog[logIdx].push({
15985                                   msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
15986                                   newVal: value,
15987                                   oldVal: last
15988                                 });
15989                               }
15990                             } else if (watch === lastDirtyWatch) {
15991                               // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
15992                               // have already been tested.
15993                               dirty = false;
15994                               break traverseScopesLoop;
15995                             }
15996                           }
15997                         } catch (e) {
15998                           $exceptionHandler(e);
15999                         }
16000                       }
16001                     }
16002
16003                     // Insanity Warning: scope depth-first traversal
16004                     // yes, this code is a bit crazy, but it works and we have tests to prove it!
16005                     // this piece should be kept in sync with the traversal in $broadcast
16006                     if (!(next = ((current.$$watchersCount && current.$$childHead) ||
16007                         (current !== target && current.$$nextSibling)))) {
16008                       while (current !== target && !(next = current.$$nextSibling)) {
16009                         current = current.$parent;
16010                       }
16011                     }
16012                   } while ((current = next));
16013
16014                   // `break traverseScopesLoop;` takes us to here
16015
16016                   if ((dirty || asyncQueue.length) && !(ttl--)) {
16017                     clearPhase();
16018                     throw $rootScopeMinErr('infdig',
16019                         '{0} $digest() iterations reached. Aborting!\n' +
16020                         'Watchers fired in the last 5 iterations: {1}',
16021                         TTL, watchLog);
16022                   }
16023
16024                 } while (dirty || asyncQueue.length);
16025
16026                 clearPhase();
16027
16028                 while (postDigestQueue.length) {
16029                   try {
16030                     postDigestQueue.shift()();
16031                   } catch (e) {
16032                     $exceptionHandler(e);
16033                   }
16034                 }
16035               },
16036
16037
16038               /**
16039                * @ngdoc event
16040                * @name $rootScope.Scope#$destroy
16041                * @eventType broadcast on scope being destroyed
16042                *
16043                * @description
16044                * Broadcasted when a scope and its children are being destroyed.
16045                *
16046                * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
16047                * clean up DOM bindings before an element is removed from the DOM.
16048                */
16049
16050               /**
16051                * @ngdoc method
16052                * @name $rootScope.Scope#$destroy
16053                * @kind function
16054                *
16055                * @description
16056                * Removes the current scope (and all of its children) from the parent scope. Removal implies
16057                * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
16058                * propagate to the current scope and its children. Removal also implies that the current
16059                * scope is eligible for garbage collection.
16060                *
16061                * The `$destroy()` is usually used by directives such as
16062                * {@link ng.directive:ngRepeat ngRepeat} for managing the
16063                * unrolling of the loop.
16064                *
16065                * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
16066                * Application code can register a `$destroy` event handler that will give it a chance to
16067                * perform any necessary cleanup.
16068                *
16069                * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
16070                * clean up DOM bindings before an element is removed from the DOM.
16071                */
16072               $destroy: function() {
16073                 // We can't destroy a scope that has been already destroyed.
16074                 if (this.$$destroyed) return;
16075                 var parent = this.$parent;
16076
16077                 this.$broadcast('$destroy');
16078                 this.$$destroyed = true;
16079
16080                 if (this === $rootScope) {
16081                   //Remove handlers attached to window when $rootScope is removed
16082                   $browser.$$applicationDestroyed();
16083                 }
16084
16085                 incrementWatchersCount(this, -this.$$watchersCount);
16086                 for (var eventName in this.$$listenerCount) {
16087                   decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
16088                 }
16089
16090                 // sever all the references to parent scopes (after this cleanup, the current scope should
16091                 // not be retained by any of our references and should be eligible for garbage collection)
16092                 if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
16093                 if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
16094                 if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
16095                 if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
16096
16097                 // Disable listeners, watchers and apply/digest methods
16098                 this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
16099                 this.$on = this.$watch = this.$watchGroup = function() { return noop; };
16100                 this.$$listeners = {};
16101
16102                 // Disconnect the next sibling to prevent `cleanUpScope` destroying those too
16103                 this.$$nextSibling = null;
16104                 cleanUpScope(this);
16105               },
16106
16107               /**
16108                * @ngdoc method
16109                * @name $rootScope.Scope#$eval
16110                * @kind function
16111                *
16112                * @description
16113                * Executes the `expression` on the current scope and returns the result. Any exceptions in
16114                * the expression are propagated (uncaught). This is useful when evaluating Angular
16115                * expressions.
16116                *
16117                * # Example
16118                * ```js
16119                    var scope = ng.$rootScope.Scope();
16120                    scope.a = 1;
16121                    scope.b = 2;
16122
16123                    expect(scope.$eval('a+b')).toEqual(3);
16124                    expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
16125                * ```
16126                *
16127                * @param {(string|function())=} expression An angular expression to be executed.
16128                *
16129                *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.
16130                *    - `function(scope)`: execute the function with the current `scope` parameter.
16131                *
16132                * @param {(object)=} locals Local variables object, useful for overriding values in scope.
16133                * @returns {*} The result of evaluating the expression.
16134                */
16135               $eval: function(expr, locals) {
16136                 return $parse(expr)(this, locals);
16137               },
16138
16139               /**
16140                * @ngdoc method
16141                * @name $rootScope.Scope#$evalAsync
16142                * @kind function
16143                *
16144                * @description
16145                * Executes the expression on the current scope at a later point in time.
16146                *
16147                * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
16148                * that:
16149                *
16150                *   - it will execute after the function that scheduled the evaluation (preferably before DOM
16151                *     rendering).
16152                *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
16153                *     `expression` execution.
16154                *
16155                * Any exceptions from the execution of the expression are forwarded to the
16156                * {@link ng.$exceptionHandler $exceptionHandler} service.
16157                *
16158                * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
16159                * will be scheduled. However, it is encouraged to always call code that changes the model
16160                * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
16161                *
16162                * @param {(string|function())=} expression An angular expression to be executed.
16163                *
16164                *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
16165                *    - `function(scope)`: execute the function with the current `scope` parameter.
16166                *
16167                * @param {(object)=} locals Local variables object, useful for overriding values in scope.
16168                */
16169               $evalAsync: function(expr, locals) {
16170                 // if we are outside of an $digest loop and this is the first time we are scheduling async
16171                 // task also schedule async auto-flush
16172                 if (!$rootScope.$$phase && !asyncQueue.length) {
16173                   $browser.defer(function() {
16174                     if (asyncQueue.length) {
16175                       $rootScope.$digest();
16176                     }
16177                   });
16178                 }
16179
16180                 asyncQueue.push({scope: this, expression: expr, locals: locals});
16181               },
16182
16183               $$postDigest: function(fn) {
16184                 postDigestQueue.push(fn);
16185               },
16186
16187               /**
16188                * @ngdoc method
16189                * @name $rootScope.Scope#$apply
16190                * @kind function
16191                *
16192                * @description
16193                * `$apply()` is used to execute an expression in angular from outside of the angular
16194                * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
16195                * Because we are calling into the angular framework we need to perform proper scope life
16196                * cycle of {@link ng.$exceptionHandler exception handling},
16197                * {@link ng.$rootScope.Scope#$digest executing watches}.
16198                *
16199                * ## Life cycle
16200                *
16201                * # Pseudo-Code of `$apply()`
16202                * ```js
16203                    function $apply(expr) {
16204                      try {
16205                        return $eval(expr);
16206                      } catch (e) {
16207                        $exceptionHandler(e);
16208                      } finally {
16209                        $root.$digest();
16210                      }
16211                    }
16212                * ```
16213                *
16214                *
16215                * Scope's `$apply()` method transitions through the following stages:
16216                *
16217                * 1. The {@link guide/expression expression} is executed using the
16218                *    {@link ng.$rootScope.Scope#$eval $eval()} method.
16219                * 2. Any exceptions from the execution of the expression are forwarded to the
16220                *    {@link ng.$exceptionHandler $exceptionHandler} service.
16221                * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
16222                *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
16223                *
16224                *
16225                * @param {(string|function())=} exp An angular expression to be executed.
16226                *
16227                *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
16228                *    - `function(scope)`: execute the function with current `scope` parameter.
16229                *
16230                * @returns {*} The result of evaluating the expression.
16231                */
16232               $apply: function(expr) {
16233                 try {
16234                   beginPhase('$apply');
16235                   try {
16236                     return this.$eval(expr);
16237                   } finally {
16238                     clearPhase();
16239                   }
16240                 } catch (e) {
16241                   $exceptionHandler(e);
16242                 } finally {
16243                   try {
16244                     $rootScope.$digest();
16245                   } catch (e) {
16246                     $exceptionHandler(e);
16247                     throw e;
16248                   }
16249                 }
16250               },
16251
16252               /**
16253                * @ngdoc method
16254                * @name $rootScope.Scope#$applyAsync
16255                * @kind function
16256                *
16257                * @description
16258                * Schedule the invocation of $apply to occur at a later time. The actual time difference
16259                * varies across browsers, but is typically around ~10 milliseconds.
16260                *
16261                * This can be used to queue up multiple expressions which need to be evaluated in the same
16262                * digest.
16263                *
16264                * @param {(string|function())=} exp An angular expression to be executed.
16265                *
16266                *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
16267                *    - `function(scope)`: execute the function with current `scope` parameter.
16268                */
16269               $applyAsync: function(expr) {
16270                 var scope = this;
16271                 expr && applyAsyncQueue.push($applyAsyncExpression);
16272                 scheduleApplyAsync();
16273
16274                 function $applyAsyncExpression() {
16275                   scope.$eval(expr);
16276                 }
16277               },
16278
16279               /**
16280                * @ngdoc method
16281                * @name $rootScope.Scope#$on
16282                * @kind function
16283                *
16284                * @description
16285                * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
16286                * discussion of event life cycle.
16287                *
16288                * The event listener function format is: `function(event, args...)`. The `event` object
16289                * passed into the listener has the following attributes:
16290                *
16291                *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
16292                *     `$broadcast`-ed.
16293                *   - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the
16294                *     event propagates through the scope hierarchy, this property is set to null.
16295                *   - `name` - `{string}`: name of the event.
16296                *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
16297                *     further event propagation (available only for events that were `$emit`-ed).
16298                *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
16299                *     to true.
16300                *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
16301                *
16302                * @param {string} name Event name to listen on.
16303                * @param {function(event, ...args)} listener Function to call when the event is emitted.
16304                * @returns {function()} Returns a deregistration function for this listener.
16305                */
16306               $on: function(name, listener) {
16307                 var namedListeners = this.$$listeners[name];
16308                 if (!namedListeners) {
16309                   this.$$listeners[name] = namedListeners = [];
16310                 }
16311                 namedListeners.push(listener);
16312
16313                 var current = this;
16314                 do {
16315                   if (!current.$$listenerCount[name]) {
16316                     current.$$listenerCount[name] = 0;
16317                   }
16318                   current.$$listenerCount[name]++;
16319                 } while ((current = current.$parent));
16320
16321                 var self = this;
16322                 return function() {
16323                   var indexOfListener = namedListeners.indexOf(listener);
16324                   if (indexOfListener !== -1) {
16325                     namedListeners[indexOfListener] = null;
16326                     decrementListenerCount(self, 1, name);
16327                   }
16328                 };
16329               },
16330
16331
16332               /**
16333                * @ngdoc method
16334                * @name $rootScope.Scope#$emit
16335                * @kind function
16336                *
16337                * @description
16338                * Dispatches an event `name` upwards through the scope hierarchy notifying the
16339                * registered {@link ng.$rootScope.Scope#$on} listeners.
16340                *
16341                * The event life cycle starts at the scope on which `$emit` was called. All
16342                * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
16343                * notified. Afterwards, the event traverses upwards toward the root scope and calls all
16344                * registered listeners along the way. The event will stop propagating if one of the listeners
16345                * cancels it.
16346                *
16347                * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
16348                * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
16349                *
16350                * @param {string} name Event name to emit.
16351                * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
16352                * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
16353                */
16354               $emit: function(name, args) {
16355                 var empty = [],
16356                     namedListeners,
16357                     scope = this,
16358                     stopPropagation = false,
16359                     event = {
16360                       name: name,
16361                       targetScope: scope,
16362                       stopPropagation: function() {stopPropagation = true;},
16363                       preventDefault: function() {
16364                         event.defaultPrevented = true;
16365                       },
16366                       defaultPrevented: false
16367                     },
16368                     listenerArgs = concat([event], arguments, 1),
16369                     i, length;
16370
16371                 do {
16372                   namedListeners = scope.$$listeners[name] || empty;
16373                   event.currentScope = scope;
16374                   for (i = 0, length = namedListeners.length; i < length; i++) {
16375
16376                     // if listeners were deregistered, defragment the array
16377                     if (!namedListeners[i]) {
16378                       namedListeners.splice(i, 1);
16379                       i--;
16380                       length--;
16381                       continue;
16382                     }
16383                     try {
16384                       //allow all listeners attached to the current scope to run
16385                       namedListeners[i].apply(null, listenerArgs);
16386                     } catch (e) {
16387                       $exceptionHandler(e);
16388                     }
16389                   }
16390                   //if any listener on the current scope stops propagation, prevent bubbling
16391                   if (stopPropagation) {
16392                     event.currentScope = null;
16393                     return event;
16394                   }
16395                   //traverse upwards
16396                   scope = scope.$parent;
16397                 } while (scope);
16398
16399                 event.currentScope = null;
16400
16401                 return event;
16402               },
16403
16404
16405               /**
16406                * @ngdoc method
16407                * @name $rootScope.Scope#$broadcast
16408                * @kind function
16409                *
16410                * @description
16411                * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
16412                * registered {@link ng.$rootScope.Scope#$on} listeners.
16413                *
16414                * The event life cycle starts at the scope on which `$broadcast` was called. All
16415                * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
16416                * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
16417                * scope and calls all registered listeners along the way. The event cannot be canceled.
16418                *
16419                * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
16420                * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
16421                *
16422                * @param {string} name Event name to broadcast.
16423                * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
16424                * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
16425                */
16426               $broadcast: function(name, args) {
16427                 var target = this,
16428                     current = target,
16429                     next = target,
16430                     event = {
16431                       name: name,
16432                       targetScope: target,
16433                       preventDefault: function() {
16434                         event.defaultPrevented = true;
16435                       },
16436                       defaultPrevented: false
16437                     };
16438
16439                 if (!target.$$listenerCount[name]) return event;
16440
16441                 var listenerArgs = concat([event], arguments, 1),
16442                     listeners, i, length;
16443
16444                 //down while you can, then up and next sibling or up and next sibling until back at root
16445                 while ((current = next)) {
16446                   event.currentScope = current;
16447                   listeners = current.$$listeners[name] || [];
16448                   for (i = 0, length = listeners.length; i < length; i++) {
16449                     // if listeners were deregistered, defragment the array
16450                     if (!listeners[i]) {
16451                       listeners.splice(i, 1);
16452                       i--;
16453                       length--;
16454                       continue;
16455                     }
16456
16457                     try {
16458                       listeners[i].apply(null, listenerArgs);
16459                     } catch (e) {
16460                       $exceptionHandler(e);
16461                     }
16462                   }
16463
16464                   // Insanity Warning: scope depth-first traversal
16465                   // yes, this code is a bit crazy, but it works and we have tests to prove it!
16466                   // this piece should be kept in sync with the traversal in $digest
16467                   // (though it differs due to having the extra check for $$listenerCount)
16468                   if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
16469                       (current !== target && current.$$nextSibling)))) {
16470                     while (current !== target && !(next = current.$$nextSibling)) {
16471                       current = current.$parent;
16472                     }
16473                   }
16474                 }
16475
16476                 event.currentScope = null;
16477                 return event;
16478               }
16479             };
16480
16481             var $rootScope = new Scope();
16482
16483             //The internal queues. Expose them on the $rootScope for debugging/testing purposes.
16484             var asyncQueue = $rootScope.$$asyncQueue = [];
16485             var postDigestQueue = $rootScope.$$postDigestQueue = [];
16486             var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];
16487
16488             return $rootScope;
16489
16490
16491             function beginPhase(phase) {
16492               if ($rootScope.$$phase) {
16493                 throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
16494               }
16495
16496               $rootScope.$$phase = phase;
16497             }
16498
16499             function clearPhase() {
16500               $rootScope.$$phase = null;
16501             }
16502
16503             function incrementWatchersCount(current, count) {
16504               do {
16505                 current.$$watchersCount += count;
16506               } while ((current = current.$parent));
16507             }
16508
16509             function decrementListenerCount(current, count, name) {
16510               do {
16511                 current.$$listenerCount[name] -= count;
16512
16513                 if (current.$$listenerCount[name] === 0) {
16514                   delete current.$$listenerCount[name];
16515                 }
16516               } while ((current = current.$parent));
16517             }
16518
16519             /**
16520              * function used as an initial value for watchers.
16521              * because it's unique we can easily tell it apart from other values
16522              */
16523             function initWatchVal() {}
16524
16525             function flushApplyAsync() {
16526               while (applyAsyncQueue.length) {
16527                 try {
16528                   applyAsyncQueue.shift()();
16529                 } catch (e) {
16530                   $exceptionHandler(e);
16531                 }
16532               }
16533               applyAsyncId = null;
16534             }
16535
16536             function scheduleApplyAsync() {
16537               if (applyAsyncId === null) {
16538                 applyAsyncId = $browser.defer(function() {
16539                   $rootScope.$apply(flushApplyAsync);
16540                 });
16541               }
16542             }
16543           }];
16544         }
16545
16546         /**
16547          * @description
16548          * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
16549          */
16550         function $$SanitizeUriProvider() {
16551           var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
16552             imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/;
16553
16554           /**
16555            * @description
16556            * Retrieves or overrides the default regular expression that is used for whitelisting of safe
16557            * urls during a[href] sanitization.
16558            *
16559            * The sanitization is a security measure aimed at prevent XSS attacks via html links.
16560            *
16561            * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
16562            * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
16563            * regular expression. If a match is found, the original url is written into the dom. Otherwise,
16564            * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
16565            *
16566            * @param {RegExp=} regexp New regexp to whitelist urls with.
16567            * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
16568            *    chaining otherwise.
16569            */
16570           this.aHrefSanitizationWhitelist = function(regexp) {
16571             if (isDefined(regexp)) {
16572               aHrefSanitizationWhitelist = regexp;
16573               return this;
16574             }
16575             return aHrefSanitizationWhitelist;
16576           };
16577
16578
16579           /**
16580            * @description
16581            * Retrieves or overrides the default regular expression that is used for whitelisting of safe
16582            * urls during img[src] sanitization.
16583            *
16584            * The sanitization is a security measure aimed at prevent XSS attacks via html links.
16585            *
16586            * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
16587            * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
16588            * regular expression. If a match is found, the original url is written into the dom. Otherwise,
16589            * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
16590            *
16591            * @param {RegExp=} regexp New regexp to whitelist urls with.
16592            * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
16593            *    chaining otherwise.
16594            */
16595           this.imgSrcSanitizationWhitelist = function(regexp) {
16596             if (isDefined(regexp)) {
16597               imgSrcSanitizationWhitelist = regexp;
16598               return this;
16599             }
16600             return imgSrcSanitizationWhitelist;
16601           };
16602
16603           this.$get = function() {
16604             return function sanitizeUri(uri, isImage) {
16605               var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
16606               var normalizedVal;
16607               normalizedVal = urlResolve(uri).href;
16608               if (normalizedVal !== '' && !normalizedVal.match(regex)) {
16609                 return 'unsafe:' + normalizedVal;
16610               }
16611               return uri;
16612             };
16613           };
16614         }
16615
16616         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
16617          *     Any commits to this file should be reviewed with security in mind.  *
16618          *   Changes to this file can potentially create security vulnerabilities. *
16619          *          An approval from 2 Core members with history of modifying      *
16620          *                         this file is required.                          *
16621          *                                                                         *
16622          *  Does the change somehow allow for arbitrary javascript to be executed? *
16623          *    Or allows for someone to change the prototype of built-in objects?   *
16624          *     Or gives undesired access to variables likes document or window?    *
16625          * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16626
16627         var $sceMinErr = minErr('$sce');
16628
16629         var SCE_CONTEXTS = {
16630           HTML: 'html',
16631           CSS: 'css',
16632           URL: 'url',
16633           // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
16634           // url.  (e.g. ng-include, script src, templateUrl)
16635           RESOURCE_URL: 'resourceUrl',
16636           JS: 'js'
16637         };
16638
16639         // Helper functions follow.
16640
16641         function adjustMatcher(matcher) {
16642           if (matcher === 'self') {
16643             return matcher;
16644           } else if (isString(matcher)) {
16645             // Strings match exactly except for 2 wildcards - '*' and '**'.
16646             // '*' matches any character except those from the set ':/.?&'.
16647             // '**' matches any character (like .* in a RegExp).
16648             // More than 2 *'s raises an error as it's ill defined.
16649             if (matcher.indexOf('***') > -1) {
16650               throw $sceMinErr('iwcard',
16651                   'Illegal sequence *** in string matcher.  String: {0}', matcher);
16652             }
16653             matcher = escapeForRegexp(matcher).
16654                           replace('\\*\\*', '.*').
16655                           replace('\\*', '[^:/.?&;]*');
16656             return new RegExp('^' + matcher + '$');
16657           } else if (isRegExp(matcher)) {
16658             // The only other type of matcher allowed is a Regexp.
16659             // Match entire URL / disallow partial matches.
16660             // Flags are reset (i.e. no global, ignoreCase or multiline)
16661             return new RegExp('^' + matcher.source + '$');
16662           } else {
16663             throw $sceMinErr('imatcher',
16664                 'Matchers may only be "self", string patterns or RegExp objects');
16665           }
16666         }
16667
16668
16669         function adjustMatchers(matchers) {
16670           var adjustedMatchers = [];
16671           if (isDefined(matchers)) {
16672             forEach(matchers, function(matcher) {
16673               adjustedMatchers.push(adjustMatcher(matcher));
16674             });
16675           }
16676           return adjustedMatchers;
16677         }
16678
16679
16680         /**
16681          * @ngdoc service
16682          * @name $sceDelegate
16683          * @kind function
16684          *
16685          * @description
16686          *
16687          * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
16688          * Contextual Escaping (SCE)} services to AngularJS.
16689          *
16690          * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
16691          * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is
16692          * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
16693          * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
16694          * work because `$sce` delegates to `$sceDelegate` for these operations.
16695          *
16696          * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
16697          *
16698          * The default instance of `$sceDelegate` should work out of the box with little pain.  While you
16699          * can override it completely to change the behavior of `$sce`, the common case would
16700          * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
16701          * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
16702          * templates.  Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
16703          * $sceDelegateProvider.resourceUrlWhitelist} and {@link
16704          * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
16705          */
16706
16707         /**
16708          * @ngdoc provider
16709          * @name $sceDelegateProvider
16710          * @description
16711          *
16712          * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
16713          * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure
16714          * that the URLs used for sourcing Angular templates are safe.  Refer {@link
16715          * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
16716          * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
16717          *
16718          * For the general details about this service in Angular, read the main page for {@link ng.$sce
16719          * Strict Contextual Escaping (SCE)}.
16720          *
16721          * **Example**:  Consider the following case. <a name="example"></a>
16722          *
16723          * - your app is hosted at url `http://myapp.example.com/`
16724          * - but some of your templates are hosted on other domains you control such as
16725          *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
16726          * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
16727          *
16728          * Here is what a secure configuration for this scenario might look like:
16729          *
16730          * ```
16731          *  angular.module('myApp', []).config(function($sceDelegateProvider) {
16732          *    $sceDelegateProvider.resourceUrlWhitelist([
16733          *      // Allow same origin resource loads.
16734          *      'self',
16735          *      // Allow loading from our assets domain.  Notice the difference between * and **.
16736          *      'http://srv*.assets.example.com/**'
16737          *    ]);
16738          *
16739          *    // The blacklist overrides the whitelist so the open redirect here is blocked.
16740          *    $sceDelegateProvider.resourceUrlBlacklist([
16741          *      'http://myapp.example.com/clickThru**'
16742          *    ]);
16743          *  });
16744          * ```
16745          */
16746
16747         function $SceDelegateProvider() {
16748           this.SCE_CONTEXTS = SCE_CONTEXTS;
16749
16750           // Resource URLs can also be trusted by policy.
16751           var resourceUrlWhitelist = ['self'],
16752               resourceUrlBlacklist = [];
16753
16754           /**
16755            * @ngdoc method
16756            * @name $sceDelegateProvider#resourceUrlWhitelist
16757            * @kind function
16758            *
16759            * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
16760            *     provided.  This must be an array or null.  A snapshot of this array is used so further
16761            *     changes to the array are ignored.
16762            *
16763            *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
16764            *     allowed in this array.
16765            *
16766            *     Note: **an empty whitelist array will block all URLs**!
16767            *
16768            * @return {Array} the currently set whitelist array.
16769            *
16770            * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
16771            * same origin resource requests.
16772            *
16773            * @description
16774            * Sets/Gets the whitelist of trusted resource URLs.
16775            */
16776           this.resourceUrlWhitelist = function(value) {
16777             if (arguments.length) {
16778               resourceUrlWhitelist = adjustMatchers(value);
16779             }
16780             return resourceUrlWhitelist;
16781           };
16782
16783           /**
16784            * @ngdoc method
16785            * @name $sceDelegateProvider#resourceUrlBlacklist
16786            * @kind function
16787            *
16788            * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
16789            *     provided.  This must be an array or null.  A snapshot of this array is used so further
16790            *     changes to the array are ignored.
16791            *
16792            *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
16793            *     allowed in this array.
16794            *
16795            *     The typical usage for the blacklist is to **block
16796            *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
16797            *     these would otherwise be trusted but actually return content from the redirected domain.
16798            *
16799            *     Finally, **the blacklist overrides the whitelist** and has the final say.
16800            *
16801            * @return {Array} the currently set blacklist array.
16802            *
16803            * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
16804            * is no blacklist.)
16805            *
16806            * @description
16807            * Sets/Gets the blacklist of trusted resource URLs.
16808            */
16809
16810           this.resourceUrlBlacklist = function(value) {
16811             if (arguments.length) {
16812               resourceUrlBlacklist = adjustMatchers(value);
16813             }
16814             return resourceUrlBlacklist;
16815           };
16816
16817           this.$get = ['$injector', function($injector) {
16818
16819             var htmlSanitizer = function htmlSanitizer(html) {
16820               throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
16821             };
16822
16823             if ($injector.has('$sanitize')) {
16824               htmlSanitizer = $injector.get('$sanitize');
16825             }
16826
16827
16828             function matchUrl(matcher, parsedUrl) {
16829               if (matcher === 'self') {
16830                 return urlIsSameOrigin(parsedUrl);
16831               } else {
16832                 // definitely a regex.  See adjustMatchers()
16833                 return !!matcher.exec(parsedUrl.href);
16834               }
16835             }
16836
16837             function isResourceUrlAllowedByPolicy(url) {
16838               var parsedUrl = urlResolve(url.toString());
16839               var i, n, allowed = false;
16840               // Ensure that at least one item from the whitelist allows this url.
16841               for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
16842                 if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
16843                   allowed = true;
16844                   break;
16845                 }
16846               }
16847               if (allowed) {
16848                 // Ensure that no item from the blacklist blocked this url.
16849                 for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
16850                   if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
16851                     allowed = false;
16852                     break;
16853                   }
16854                 }
16855               }
16856               return allowed;
16857             }
16858
16859             function generateHolderType(Base) {
16860               var holderType = function TrustedValueHolderType(trustedValue) {
16861                 this.$$unwrapTrustedValue = function() {
16862                   return trustedValue;
16863                 };
16864               };
16865               if (Base) {
16866                 holderType.prototype = new Base();
16867               }
16868               holderType.prototype.valueOf = function sceValueOf() {
16869                 return this.$$unwrapTrustedValue();
16870               };
16871               holderType.prototype.toString = function sceToString() {
16872                 return this.$$unwrapTrustedValue().toString();
16873               };
16874               return holderType;
16875             }
16876
16877             var trustedValueHolderBase = generateHolderType(),
16878                 byType = {};
16879
16880             byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
16881             byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
16882             byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
16883             byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
16884             byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
16885
16886             /**
16887              * @ngdoc method
16888              * @name $sceDelegate#trustAs
16889              *
16890              * @description
16891              * Returns an object that is trusted by angular for use in specified strict
16892              * contextual escaping contexts (such as ng-bind-html, ng-include, any src
16893              * attribute interpolation, any dom event binding attribute interpolation
16894              * such as for onclick,  etc.) that uses the provided value.
16895              * See {@link ng.$sce $sce} for enabling strict contextual escaping.
16896              *
16897              * @param {string} type The kind of context in which this value is safe for use.  e.g. url,
16898              *   resourceUrl, html, js and css.
16899              * @param {*} value The value that that should be considered trusted/safe.
16900              * @returns {*} A value that can be used to stand in for the provided `value` in places
16901              * where Angular expects a $sce.trustAs() return value.
16902              */
16903             function trustAs(type, trustedValue) {
16904               var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
16905               if (!Constructor) {
16906                 throw $sceMinErr('icontext',
16907                     'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
16908                     type, trustedValue);
16909               }
16910               if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {
16911                 return trustedValue;
16912               }
16913               // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting
16914               // mutable objects, we ensure here that the value passed in is actually a string.
16915               if (typeof trustedValue !== 'string') {
16916                 throw $sceMinErr('itype',
16917                     'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
16918                     type);
16919               }
16920               return new Constructor(trustedValue);
16921             }
16922
16923             /**
16924              * @ngdoc method
16925              * @name $sceDelegate#valueOf
16926              *
16927              * @description
16928              * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
16929              * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
16930              * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
16931              *
16932              * If the passed parameter is not a value that had been returned by {@link
16933              * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
16934              *
16935              * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
16936              *      call or anything else.
16937              * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
16938              *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns
16939              *     `value` unchanged.
16940              */
16941             function valueOf(maybeTrusted) {
16942               if (maybeTrusted instanceof trustedValueHolderBase) {
16943                 return maybeTrusted.$$unwrapTrustedValue();
16944               } else {
16945                 return maybeTrusted;
16946               }
16947             }
16948
16949             /**
16950              * @ngdoc method
16951              * @name $sceDelegate#getTrusted
16952              *
16953              * @description
16954              * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
16955              * returns the originally supplied value if the queried context type is a supertype of the
16956              * created type.  If this condition isn't satisfied, throws an exception.
16957              *
16958              * @param {string} type The kind of context in which this value is to be used.
16959              * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
16960              *     `$sceDelegate.trustAs`} call.
16961              * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
16962              *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.
16963              */
16964             function getTrusted(type, maybeTrusted) {
16965               if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {
16966                 return maybeTrusted;
16967               }
16968               var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
16969               if (constructor && maybeTrusted instanceof constructor) {
16970                 return maybeTrusted.$$unwrapTrustedValue();
16971               }
16972               // If we get here, then we may only take one of two actions.
16973               // 1. sanitize the value for the requested type, or
16974               // 2. throw an exception.
16975               if (type === SCE_CONTEXTS.RESOURCE_URL) {
16976                 if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
16977                   return maybeTrusted;
16978                 } else {
16979                   throw $sceMinErr('insecurl',
16980                       'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',
16981                       maybeTrusted.toString());
16982                 }
16983               } else if (type === SCE_CONTEXTS.HTML) {
16984                 return htmlSanitizer(maybeTrusted);
16985               }
16986               throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
16987             }
16988
16989             return { trustAs: trustAs,
16990                      getTrusted: getTrusted,
16991                      valueOf: valueOf };
16992           }];
16993         }
16994
16995
16996         /**
16997          * @ngdoc provider
16998          * @name $sceProvider
16999          * @description
17000          *
17001          * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
17002          * -   enable/disable Strict Contextual Escaping (SCE) in a module
17003          * -   override the default implementation with a custom delegate
17004          *
17005          * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
17006          */
17007
17008         /* jshint maxlen: false*/
17009
17010         /**
17011          * @ngdoc service
17012          * @name $sce
17013          * @kind function
17014          *
17015          * @description
17016          *
17017          * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
17018          *
17019          * # Strict Contextual Escaping
17020          *
17021          * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
17022          * contexts to result in a value that is marked as safe to use for that context.  One example of
17023          * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer
17024          * to these contexts as privileged or SCE contexts.
17025          *
17026          * As of version 1.2, Angular ships with SCE enabled by default.
17027          *
17028          * Note:  When enabled (the default), IE<11 in quirks mode is not supported.  In this mode, IE<11 allow
17029          * one to execute arbitrary javascript by the use of the expression() syntax.  Refer
17030          * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
17031          * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
17032          * to the top of your HTML document.
17033          *
17034          * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
17035          * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
17036          *
17037          * Here's an example of a binding in a privileged context:
17038          *
17039          * ```
17040          * <input ng-model="userHtml" aria-label="User input">
17041          * <div ng-bind-html="userHtml"></div>
17042          * ```
17043          *
17044          * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE
17045          * disabled, this application allows the user to render arbitrary HTML into the DIV.
17046          * In a more realistic example, one may be rendering user comments, blog articles, etc. via
17047          * bindings.  (HTML is just one example of a context where rendering user controlled input creates
17048          * security vulnerabilities.)
17049          *
17050          * For the case of HTML, you might use a library, either on the client side, or on the server side,
17051          * to sanitize unsafe HTML before binding to the value and rendering it in the document.
17052          *
17053          * How would you ensure that every place that used these types of bindings was bound to a value that
17054          * was sanitized by your library (or returned as safe for rendering by your server?)  How can you
17055          * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
17056          * properties/fields and forgot to update the binding to the sanitized value?
17057          *
17058          * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
17059          * determine that something explicitly says it's safe to use a value for binding in that
17060          * context.  You can then audit your code (a simple grep would do) to ensure that this is only done
17061          * for those values that you can easily tell are safe - because they were received from your server,
17062          * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps
17063          * allowing only the files in a specific directory to do this.  Ensuring that the internal API
17064          * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
17065          *
17066          * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
17067          * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
17068          * obtain values that will be accepted by SCE / privileged contexts.
17069          *
17070          *
17071          * ## How does it work?
17072          *
17073          * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
17074          * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link
17075          * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
17076          * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
17077          *
17078          * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
17079          * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly
17080          * simplified):
17081          *
17082          * ```
17083          * var ngBindHtmlDirective = ['$sce', function($sce) {
17084          *   return function(scope, element, attr) {
17085          *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
17086          *       element.html(value || '');
17087          *     });
17088          *   };
17089          * }];
17090          * ```
17091          *
17092          * ## Impact on loading templates
17093          *
17094          * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
17095          * `templateUrl`'s specified by {@link guide/directive directives}.
17096          *
17097          * By default, Angular only loads templates from the same domain and protocol as the application
17098          * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl
17099          * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or
17100          * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
17101          * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
17102          *
17103          * *Please note*:
17104          * The browser's
17105          * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
17106          * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
17107          * policy apply in addition to this and may further restrict whether the template is successfully
17108          * loaded.  This means that without the right CORS policy, loading templates from a different domain
17109          * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some
17110          * browsers.
17111          *
17112          * ## This feels like too much overhead
17113          *
17114          * It's important to remember that SCE only applies to interpolation expressions.
17115          *
17116          * If your expressions are constant literals, they're automatically trusted and you don't need to
17117          * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
17118          * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
17119          *
17120          * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
17121          * through {@link ng.$sce#getTrusted $sce.getTrusted}.  SCE doesn't play a role here.
17122          *
17123          * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
17124          * templates in `ng-include` from your application's domain without having to even know about SCE.
17125          * It blocks loading templates from other domains or loading templates over http from an https
17126          * served document.  You can change these by setting your own custom {@link
17127          * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
17128          * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
17129          *
17130          * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an
17131          * application that's secure and can be audited to verify that with much more ease than bolting
17132          * security onto an application later.
17133          *
17134          * <a name="contexts"></a>
17135          * ## What trusted context types are supported?
17136          *
17137          * | Context             | Notes          |
17138          * |---------------------|----------------|
17139          * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
17140          * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |
17141          * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
17142          * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
17143          * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |
17144          *
17145          * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
17146          *
17147          *  Each element in these arrays must be one of the following:
17148          *
17149          *  - **'self'**
17150          *    - The special **string**, `'self'`, can be used to match against all URLs of the **same
17151          *      domain** as the application document using the **same protocol**.
17152          *  - **String** (except the special value `'self'`)
17153          *    - The string is matched against the full *normalized / absolute URL* of the resource
17154          *      being tested (substring matches are not good enough.)
17155          *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters
17156          *      match themselves.
17157          *    - `*`: matches zero or more occurrences of any character other than one of the following 6
17158          *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'.  It's a useful wildcard for use
17159          *      in a whitelist.
17160          *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not
17161          *      appropriate for use in a scheme, domain, etc. as it would match too much.  (e.g.
17162          *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
17163          *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.
17164          *      http://foo.example.com/templates/**).
17165          *  - **RegExp** (*see caveat below*)
17166          *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax
17167          *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to
17168          *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should
17169          *      have good test coverage).  For instance, the use of `.` in the regex is correct only in a
17170          *      small number of cases.  A `.` character in the regex used when matching the scheme or a
17171          *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It
17172          *      is highly recommended to use the string patterns and only fall back to regular expressions
17173          *      as a last resort.
17174          *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is
17175          *      matched against the **entire** *normalized / absolute URL* of the resource being tested
17176          *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags
17177          *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.
17178          *    - If you are generating your JavaScript from some other templating engine (not
17179          *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
17180          *      remember to escape your regular expression (and be aware that you might need more than
17181          *      one level of escaping depending on your templating engine and the way you interpolated
17182          *      the value.)  Do make use of your platform's escaping mechanism as it might be good
17183          *      enough before coding your own.  E.g. Ruby has
17184          *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
17185          *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
17186          *      Javascript lacks a similar built in function for escaping.  Take a look at Google
17187          *      Closure library's [goog.string.regExpEscape(s)](
17188          *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
17189          *
17190          * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
17191          *
17192          * ## Show me an example using SCE.
17193          *
17194          * <example module="mySceApp" deps="angular-sanitize.js">
17195          * <file name="index.html">
17196          *   <div ng-controller="AppController as myCtrl">
17197          *     <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
17198          *     <b>User comments</b><br>
17199          *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
17200          *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an
17201          *     exploit.
17202          *     <div class="well">
17203          *       <div ng-repeat="userComment in myCtrl.userComments">
17204          *         <b>{{userComment.name}}</b>:
17205          *         <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
17206          *         <br>
17207          *       </div>
17208          *     </div>
17209          *   </div>
17210          * </file>
17211          *
17212          * <file name="script.js">
17213          *   angular.module('mySceApp', ['ngSanitize'])
17214          *     .controller('AppController', ['$http', '$templateCache', '$sce',
17215          *       function($http, $templateCache, $sce) {
17216          *         var self = this;
17217          *         $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
17218          *           self.userComments = userComments;
17219          *         });
17220          *         self.explicitlyTrustedHtml = $sce.trustAsHtml(
17221          *             '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
17222          *             'sanitization.&quot;">Hover over this text.</span>');
17223          *       }]);
17224          * </file>
17225          *
17226          * <file name="test_data.json">
17227          * [
17228          *   { "name": "Alice",
17229          *     "htmlComment":
17230          *         "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
17231          *   },
17232          *   { "name": "Bob",
17233          *     "htmlComment": "<i>Yes!</i>  Am I the only other one?"
17234          *   }
17235          * ]
17236          * </file>
17237          *
17238          * <file name="protractor.js" type="protractor">
17239          *   describe('SCE doc demo', function() {
17240          *     it('should sanitize untrusted values', function() {
17241          *       expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
17242          *           .toBe('<span>Is <i>anyone</i> reading this?</span>');
17243          *     });
17244          *
17245          *     it('should NOT sanitize explicitly trusted values', function() {
17246          *       expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
17247          *           '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
17248          *           'sanitization.&quot;">Hover over this text.</span>');
17249          *     });
17250          *   });
17251          * </file>
17252          * </example>
17253          *
17254          *
17255          *
17256          * ## Can I disable SCE completely?
17257          *
17258          * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits
17259          * for little coding overhead.  It will be much harder to take an SCE disabled application and
17260          * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE
17261          * for cases where you have a lot of existing code that was written before SCE was introduced and
17262          * you're migrating them a module at a time.
17263          *
17264          * That said, here's how you can completely disable SCE:
17265          *
17266          * ```
17267          * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
17268          *   // Completely disable SCE.  For demonstration purposes only!
17269          *   // Do not use in new projects.
17270          *   $sceProvider.enabled(false);
17271          * });
17272          * ```
17273          *
17274          */
17275         /* jshint maxlen: 100 */
17276
17277         function $SceProvider() {
17278           var enabled = true;
17279
17280           /**
17281            * @ngdoc method
17282            * @name $sceProvider#enabled
17283            * @kind function
17284            *
17285            * @param {boolean=} value If provided, then enables/disables SCE.
17286            * @return {boolean} true if SCE is enabled, false otherwise.
17287            *
17288            * @description
17289            * Enables/disables SCE and returns the current value.
17290            */
17291           this.enabled = function(value) {
17292             if (arguments.length) {
17293               enabled = !!value;
17294             }
17295             return enabled;
17296           };
17297
17298
17299           /* Design notes on the default implementation for SCE.
17300            *
17301            * The API contract for the SCE delegate
17302            * -------------------------------------
17303            * The SCE delegate object must provide the following 3 methods:
17304            *
17305            * - trustAs(contextEnum, value)
17306            *     This method is used to tell the SCE service that the provided value is OK to use in the
17307            *     contexts specified by contextEnum.  It must return an object that will be accepted by
17308            *     getTrusted() for a compatible contextEnum and return this value.
17309            *
17310            * - valueOf(value)
17311            *     For values that were not produced by trustAs(), return them as is.  For values that were
17312            *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if
17313            *     trustAs is wrapping the given values into some type, this operation unwraps it when given
17314            *     such a value.
17315            *
17316            * - getTrusted(contextEnum, value)
17317            *     This function should return the a value that is safe to use in the context specified by
17318            *     contextEnum or throw and exception otherwise.
17319            *
17320            * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
17321            * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For
17322            * instance, an implementation could maintain a registry of all trusted objects by context.  In
17323            * such a case, trustAs() would return the same object that was passed in.  getTrusted() would
17324            * return the same object passed in if it was found in the registry under a compatible context or
17325            * throw an exception otherwise.  An implementation might only wrap values some of the time based
17326            * on some criteria.  getTrusted() might return a value and not throw an exception for special
17327            * constants or objects even if not wrapped.  All such implementations fulfill this contract.
17328            *
17329            *
17330            * A note on the inheritance model for SCE contexts
17331            * ------------------------------------------------
17332            * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This
17333            * is purely an implementation details.
17334            *
17335            * The contract is simply this:
17336            *
17337            *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
17338            *     will also succeed.
17339            *
17340            * Inheritance happens to capture this in a natural way.  In some future, we
17341            * may not use inheritance anymore.  That is OK because no code outside of
17342            * sce.js and sceSpecs.js would need to be aware of this detail.
17343            */
17344
17345           this.$get = ['$parse', '$sceDelegate', function(
17346                         $parse,   $sceDelegate) {
17347             // Prereq: Ensure that we're not running in IE<11 quirks mode.  In that mode, IE < 11 allow
17348             // the "expression(javascript expression)" syntax which is insecure.
17349             if (enabled && msie < 8) {
17350               throw $sceMinErr('iequirks',
17351                 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
17352                 'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +
17353                 'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');
17354             }
17355
17356             var sce = shallowCopy(SCE_CONTEXTS);
17357
17358             /**
17359              * @ngdoc method
17360              * @name $sce#isEnabled
17361              * @kind function
17362              *
17363              * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you
17364              * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
17365              *
17366              * @description
17367              * Returns a boolean indicating if SCE is enabled.
17368              */
17369             sce.isEnabled = function() {
17370               return enabled;
17371             };
17372             sce.trustAs = $sceDelegate.trustAs;
17373             sce.getTrusted = $sceDelegate.getTrusted;
17374             sce.valueOf = $sceDelegate.valueOf;
17375
17376             if (!enabled) {
17377               sce.trustAs = sce.getTrusted = function(type, value) { return value; };
17378               sce.valueOf = identity;
17379             }
17380
17381             /**
17382              * @ngdoc method
17383              * @name $sce#parseAs
17384              *
17385              * @description
17386              * Converts Angular {@link guide/expression expression} into a function.  This is like {@link
17387              * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it
17388              * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
17389              * *result*)}
17390              *
17391              * @param {string} type The kind of SCE context in which this result will be used.
17392              * @param {string} expression String expression to compile.
17393              * @returns {function(context, locals)} a function which represents the compiled expression:
17394              *
17395              *    * `context` – `{object}` – an object against which any expressions embedded in the strings
17396              *      are evaluated against (typically a scope object).
17397              *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
17398              *      `context`.
17399              */
17400             sce.parseAs = function sceParseAs(type, expr) {
17401               var parsed = $parse(expr);
17402               if (parsed.literal && parsed.constant) {
17403                 return parsed;
17404               } else {
17405                 return $parse(expr, function(value) {
17406                   return sce.getTrusted(type, value);
17407                 });
17408               }
17409             };
17410
17411             /**
17412              * @ngdoc method
17413              * @name $sce#trustAs
17414              *
17415              * @description
17416              * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.  As such,
17417              * returns an object that is trusted by angular for use in specified strict contextual
17418              * escaping contexts (such as ng-bind-html, ng-include, any src attribute
17419              * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)
17420              * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual
17421              * escaping.
17422              *
17423              * @param {string} type The kind of context in which this value is safe for use.  e.g. url,
17424              *   resourceUrl, html, js and css.
17425              * @param {*} value The value that that should be considered trusted/safe.
17426              * @returns {*} A value that can be used to stand in for the provided `value` in places
17427              * where Angular expects a $sce.trustAs() return value.
17428              */
17429
17430             /**
17431              * @ngdoc method
17432              * @name $sce#trustAsHtml
17433              *
17434              * @description
17435              * Shorthand method.  `$sce.trustAsHtml(value)` →
17436              *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
17437              *
17438              * @param {*} value The value to trustAs.
17439              * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
17440              *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives
17441              *     only accept expressions that are either literal constants or are the
17442              *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)
17443              */
17444
17445             /**
17446              * @ngdoc method
17447              * @name $sce#trustAsUrl
17448              *
17449              * @description
17450              * Shorthand method.  `$sce.trustAsUrl(value)` →
17451              *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
17452              *
17453              * @param {*} value The value to trustAs.
17454              * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
17455              *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives
17456              *     only accept expressions that are either literal constants or are the
17457              *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)
17458              */
17459
17460             /**
17461              * @ngdoc method
17462              * @name $sce#trustAsResourceUrl
17463              *
17464              * @description
17465              * Shorthand method.  `$sce.trustAsResourceUrl(value)` →
17466              *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
17467              *
17468              * @param {*} value The value to trustAs.
17469              * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
17470              *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives
17471              *     only accept expressions that are either literal constants or are the return
17472              *     value of {@link ng.$sce#trustAs $sce.trustAs}.)
17473              */
17474
17475             /**
17476              * @ngdoc method
17477              * @name $sce#trustAsJs
17478              *
17479              * @description
17480              * Shorthand method.  `$sce.trustAsJs(value)` →
17481              *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
17482              *
17483              * @param {*} value The value to trustAs.
17484              * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
17485              *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives
17486              *     only accept expressions that are either literal constants or are the
17487              *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)
17488              */
17489
17490             /**
17491              * @ngdoc method
17492              * @name $sce#getTrusted
17493              *
17494              * @description
17495              * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,
17496              * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
17497              * originally supplied value if the queried context type is a supertype of the created type.
17498              * If this condition isn't satisfied, throws an exception.
17499              *
17500              * @param {string} type The kind of context in which this value is to be used.
17501              * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
17502              *                         call.
17503              * @returns {*} The value the was originally provided to
17504              *              {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
17505              *              Otherwise, throws an exception.
17506              */
17507
17508             /**
17509              * @ngdoc method
17510              * @name $sce#getTrustedHtml
17511              *
17512              * @description
17513              * Shorthand method.  `$sce.getTrustedHtml(value)` →
17514              *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
17515              *
17516              * @param {*} value The value to pass to `$sce.getTrusted`.
17517              * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
17518              */
17519
17520             /**
17521              * @ngdoc method
17522              * @name $sce#getTrustedCss
17523              *
17524              * @description
17525              * Shorthand method.  `$sce.getTrustedCss(value)` →
17526              *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
17527              *
17528              * @param {*} value The value to pass to `$sce.getTrusted`.
17529              * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
17530              */
17531
17532             /**
17533              * @ngdoc method
17534              * @name $sce#getTrustedUrl
17535              *
17536              * @description
17537              * Shorthand method.  `$sce.getTrustedUrl(value)` →
17538              *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
17539              *
17540              * @param {*} value The value to pass to `$sce.getTrusted`.
17541              * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
17542              */
17543
17544             /**
17545              * @ngdoc method
17546              * @name $sce#getTrustedResourceUrl
17547              *
17548              * @description
17549              * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →
17550              *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
17551              *
17552              * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
17553              * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
17554              */
17555
17556             /**
17557              * @ngdoc method
17558              * @name $sce#getTrustedJs
17559              *
17560              * @description
17561              * Shorthand method.  `$sce.getTrustedJs(value)` →
17562              *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
17563              *
17564              * @param {*} value The value to pass to `$sce.getTrusted`.
17565              * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
17566              */
17567
17568             /**
17569              * @ngdoc method
17570              * @name $sce#parseAsHtml
17571              *
17572              * @description
17573              * Shorthand method.  `$sce.parseAsHtml(expression string)` →
17574              *     {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
17575              *
17576              * @param {string} expression String expression to compile.
17577              * @returns {function(context, locals)} a function which represents the compiled expression:
17578              *
17579              *    * `context` – `{object}` – an object against which any expressions embedded in the strings
17580              *      are evaluated against (typically a scope object).
17581              *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
17582              *      `context`.
17583              */
17584
17585             /**
17586              * @ngdoc method
17587              * @name $sce#parseAsCss
17588              *
17589              * @description
17590              * Shorthand method.  `$sce.parseAsCss(value)` →
17591              *     {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
17592              *
17593              * @param {string} expression String expression to compile.
17594              * @returns {function(context, locals)} a function which represents the compiled expression:
17595              *
17596              *    * `context` – `{object}` – an object against which any expressions embedded in the strings
17597              *      are evaluated against (typically a scope object).
17598              *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
17599              *      `context`.
17600              */
17601
17602             /**
17603              * @ngdoc method
17604              * @name $sce#parseAsUrl
17605              *
17606              * @description
17607              * Shorthand method.  `$sce.parseAsUrl(value)` →
17608              *     {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
17609              *
17610              * @param {string} expression String expression to compile.
17611              * @returns {function(context, locals)} a function which represents the compiled expression:
17612              *
17613              *    * `context` – `{object}` – an object against which any expressions embedded in the strings
17614              *      are evaluated against (typically a scope object).
17615              *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
17616              *      `context`.
17617              */
17618
17619             /**
17620              * @ngdoc method
17621              * @name $sce#parseAsResourceUrl
17622              *
17623              * @description
17624              * Shorthand method.  `$sce.parseAsResourceUrl(value)` →
17625              *     {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
17626              *
17627              * @param {string} expression String expression to compile.
17628              * @returns {function(context, locals)} a function which represents the compiled expression:
17629              *
17630              *    * `context` – `{object}` – an object against which any expressions embedded in the strings
17631              *      are evaluated against (typically a scope object).
17632              *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
17633              *      `context`.
17634              */
17635
17636             /**
17637              * @ngdoc method
17638              * @name $sce#parseAsJs
17639              *
17640              * @description
17641              * Shorthand method.  `$sce.parseAsJs(value)` →
17642              *     {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
17643              *
17644              * @param {string} expression String expression to compile.
17645              * @returns {function(context, locals)} a function which represents the compiled expression:
17646              *
17647              *    * `context` – `{object}` – an object against which any expressions embedded in the strings
17648              *      are evaluated against (typically a scope object).
17649              *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
17650              *      `context`.
17651              */
17652
17653             // Shorthand delegations.
17654             var parse = sce.parseAs,
17655                 getTrusted = sce.getTrusted,
17656                 trustAs = sce.trustAs;
17657
17658             forEach(SCE_CONTEXTS, function(enumValue, name) {
17659               var lName = lowercase(name);
17660               sce[camelCase("parse_as_" + lName)] = function(expr) {
17661                 return parse(enumValue, expr);
17662               };
17663               sce[camelCase("get_trusted_" + lName)] = function(value) {
17664                 return getTrusted(enumValue, value);
17665               };
17666               sce[camelCase("trust_as_" + lName)] = function(value) {
17667                 return trustAs(enumValue, value);
17668               };
17669             });
17670
17671             return sce;
17672           }];
17673         }
17674
17675         /**
17676          * !!! This is an undocumented "private" service !!!
17677          *
17678          * @name $sniffer
17679          * @requires $window
17680          * @requires $document
17681          *
17682          * @property {boolean} history Does the browser support html5 history api ?
17683          * @property {boolean} transitions Does the browser support CSS transition events ?
17684          * @property {boolean} animations Does the browser support CSS animation events ?
17685          *
17686          * @description
17687          * This is very simple implementation of testing browser's features.
17688          */
17689         function $SnifferProvider() {
17690           this.$get = ['$window', '$document', function($window, $document) {
17691             var eventSupport = {},
17692                 android =
17693                   toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
17694                 boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
17695                 document = $document[0] || {},
17696                 vendorPrefix,
17697                 vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
17698                 bodyStyle = document.body && document.body.style,
17699                 transitions = false,
17700                 animations = false,
17701                 match;
17702
17703             if (bodyStyle) {
17704               for (var prop in bodyStyle) {
17705                 if (match = vendorRegex.exec(prop)) {
17706                   vendorPrefix = match[0];
17707                   vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
17708                   break;
17709                 }
17710               }
17711
17712               if (!vendorPrefix) {
17713                 vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
17714               }
17715
17716               transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
17717               animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
17718
17719               if (android && (!transitions ||  !animations)) {
17720                 transitions = isString(bodyStyle.webkitTransition);
17721                 animations = isString(bodyStyle.webkitAnimation);
17722               }
17723             }
17724
17725
17726             return {
17727               // Android has history.pushState, but it does not update location correctly
17728               // so let's not use the history API at all.
17729               // http://code.google.com/p/android/issues/detail?id=17471
17730               // https://github.com/angular/angular.js/issues/904
17731
17732               // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
17733               // so let's not use the history API also
17734               // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
17735               // jshint -W018
17736               history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
17737               // jshint +W018
17738               hasEvent: function(event) {
17739                 // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
17740                 // it. In particular the event is not fired when backspace or delete key are pressed or
17741                 // when cut operation is performed.
17742                 // IE10+ implements 'input' event but it erroneously fires under various situations,
17743                 // e.g. when placeholder changes, or a form is focused.
17744                 if (event === 'input' && msie <= 11) return false;
17745
17746                 if (isUndefined(eventSupport[event])) {
17747                   var divElm = document.createElement('div');
17748                   eventSupport[event] = 'on' + event in divElm;
17749                 }
17750
17751                 return eventSupport[event];
17752               },
17753               csp: csp(),
17754               vendorPrefix: vendorPrefix,
17755               transitions: transitions,
17756               animations: animations,
17757               android: android
17758             };
17759           }];
17760         }
17761
17762         var $compileMinErr = minErr('$compile');
17763
17764         /**
17765          * @ngdoc service
17766          * @name $templateRequest
17767          *
17768          * @description
17769          * The `$templateRequest` service runs security checks then downloads the provided template using
17770          * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
17771          * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
17772          * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
17773          * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
17774          * when `tpl` is of type string and `$templateCache` has the matching entry.
17775          *
17776          * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
17777          * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
17778          *
17779          * @return {Promise} a promise for the HTTP response data of the given URL.
17780          *
17781          * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
17782          */
17783         function $TemplateRequestProvider() {
17784           this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
17785             function handleRequestFn(tpl, ignoreRequestError) {
17786               handleRequestFn.totalPendingRequests++;
17787
17788               // We consider the template cache holds only trusted templates, so
17789               // there's no need to go through whitelisting again for keys that already
17790               // are included in there. This also makes Angular accept any script
17791               // directive, no matter its name. However, we still need to unwrap trusted
17792               // types.
17793               if (!isString(tpl) || !$templateCache.get(tpl)) {
17794                 tpl = $sce.getTrustedResourceUrl(tpl);
17795               }
17796
17797               var transformResponse = $http.defaults && $http.defaults.transformResponse;
17798
17799               if (isArray(transformResponse)) {
17800                 transformResponse = transformResponse.filter(function(transformer) {
17801                   return transformer !== defaultHttpResponseTransform;
17802                 });
17803               } else if (transformResponse === defaultHttpResponseTransform) {
17804                 transformResponse = null;
17805               }
17806
17807               var httpOptions = {
17808                 cache: $templateCache,
17809                 transformResponse: transformResponse
17810               };
17811
17812               return $http.get(tpl, httpOptions)
17813                 ['finally'](function() {
17814                   handleRequestFn.totalPendingRequests--;
17815                 })
17816                 .then(function(response) {
17817                   $templateCache.put(tpl, response.data);
17818                   return response.data;
17819                 }, handleError);
17820
17821               function handleError(resp) {
17822                 if (!ignoreRequestError) {
17823                   throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})',
17824                     tpl, resp.status, resp.statusText);
17825                 }
17826                 return $q.reject(resp);
17827               }
17828             }
17829
17830             handleRequestFn.totalPendingRequests = 0;
17831
17832             return handleRequestFn;
17833           }];
17834         }
17835
17836         function $$TestabilityProvider() {
17837           this.$get = ['$rootScope', '$browser', '$location',
17838                function($rootScope,   $browser,   $location) {
17839
17840             /**
17841              * @name $testability
17842              *
17843              * @description
17844              * The private $$testability service provides a collection of methods for use when debugging
17845              * or by automated test and debugging tools.
17846              */
17847             var testability = {};
17848
17849             /**
17850              * @name $$testability#findBindings
17851              *
17852              * @description
17853              * Returns an array of elements that are bound (via ng-bind or {{}})
17854              * to expressions matching the input.
17855              *
17856              * @param {Element} element The element root to search from.
17857              * @param {string} expression The binding expression to match.
17858              * @param {boolean} opt_exactMatch If true, only returns exact matches
17859              *     for the expression. Filters and whitespace are ignored.
17860              */
17861             testability.findBindings = function(element, expression, opt_exactMatch) {
17862               var bindings = element.getElementsByClassName('ng-binding');
17863               var matches = [];
17864               forEach(bindings, function(binding) {
17865                 var dataBinding = angular.element(binding).data('$binding');
17866                 if (dataBinding) {
17867                   forEach(dataBinding, function(bindingName) {
17868                     if (opt_exactMatch) {
17869                       var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
17870                       if (matcher.test(bindingName)) {
17871                         matches.push(binding);
17872                       }
17873                     } else {
17874                       if (bindingName.indexOf(expression) != -1) {
17875                         matches.push(binding);
17876                       }
17877                     }
17878                   });
17879                 }
17880               });
17881               return matches;
17882             };
17883
17884             /**
17885              * @name $$testability#findModels
17886              *
17887              * @description
17888              * Returns an array of elements that are two-way found via ng-model to
17889              * expressions matching the input.
17890              *
17891              * @param {Element} element The element root to search from.
17892              * @param {string} expression The model expression to match.
17893              * @param {boolean} opt_exactMatch If true, only returns exact matches
17894              *     for the expression.
17895              */
17896             testability.findModels = function(element, expression, opt_exactMatch) {
17897               var prefixes = ['ng-', 'data-ng-', 'ng\\:'];
17898               for (var p = 0; p < prefixes.length; ++p) {
17899                 var attributeEquals = opt_exactMatch ? '=' : '*=';
17900                 var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]';
17901                 var elements = element.querySelectorAll(selector);
17902                 if (elements.length) {
17903                   return elements;
17904                 }
17905               }
17906             };
17907
17908             /**
17909              * @name $$testability#getLocation
17910              *
17911              * @description
17912              * Shortcut for getting the location in a browser agnostic way. Returns
17913              *     the path, search, and hash. (e.g. /path?a=b#hash)
17914              */
17915             testability.getLocation = function() {
17916               return $location.url();
17917             };
17918
17919             /**
17920              * @name $$testability#setLocation
17921              *
17922              * @description
17923              * Shortcut for navigating to a location without doing a full page reload.
17924              *
17925              * @param {string} url The location url (path, search and hash,
17926              *     e.g. /path?a=b#hash) to go to.
17927              */
17928             testability.setLocation = function(url) {
17929               if (url !== $location.url()) {
17930                 $location.url(url);
17931                 $rootScope.$digest();
17932               }
17933             };
17934
17935             /**
17936              * @name $$testability#whenStable
17937              *
17938              * @description
17939              * Calls the callback when $timeout and $http requests are completed.
17940              *
17941              * @param {function} callback
17942              */
17943             testability.whenStable = function(callback) {
17944               $browser.notifyWhenNoOutstandingRequests(callback);
17945             };
17946
17947             return testability;
17948           }];
17949         }
17950
17951         function $TimeoutProvider() {
17952           this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
17953                function($rootScope,   $browser,   $q,   $$q,   $exceptionHandler) {
17954
17955             var deferreds = {};
17956
17957
17958              /**
17959               * @ngdoc service
17960               * @name $timeout
17961               *
17962               * @description
17963               * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
17964               * block and delegates any exceptions to
17965               * {@link ng.$exceptionHandler $exceptionHandler} service.
17966               *
17967               * The return value of calling `$timeout` is a promise, which will be resolved when
17968               * the delay has passed and the timeout function, if provided, is executed.
17969               *
17970               * To cancel a timeout request, call `$timeout.cancel(promise)`.
17971               *
17972               * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
17973               * synchronously flush the queue of deferred functions.
17974               *
17975               * If you only want a promise that will be resolved after some specified delay
17976               * then you can call `$timeout` without the `fn` function.
17977               *
17978               * @param {function()=} fn A function, whose execution should be delayed.
17979               * @param {number=} [delay=0] Delay in milliseconds.
17980               * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
17981               *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
17982               * @param {...*=} Pass additional parameters to the executed function.
17983               * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
17984               *   promise will be resolved with is the return value of the `fn` function.
17985               *
17986               */
17987             function timeout(fn, delay, invokeApply) {
17988               if (!isFunction(fn)) {
17989                 invokeApply = delay;
17990                 delay = fn;
17991                 fn = noop;
17992               }
17993
17994               var args = sliceArgs(arguments, 3),
17995                   skipApply = (isDefined(invokeApply) && !invokeApply),
17996                   deferred = (skipApply ? $$q : $q).defer(),
17997                   promise = deferred.promise,
17998                   timeoutId;
17999
18000               timeoutId = $browser.defer(function() {
18001                 try {
18002                   deferred.resolve(fn.apply(null, args));
18003                 } catch (e) {
18004                   deferred.reject(e);
18005                   $exceptionHandler(e);
18006                 }
18007                 finally {
18008                   delete deferreds[promise.$$timeoutId];
18009                 }
18010
18011                 if (!skipApply) $rootScope.$apply();
18012               }, delay);
18013
18014               promise.$$timeoutId = timeoutId;
18015               deferreds[timeoutId] = deferred;
18016
18017               return promise;
18018             }
18019
18020
18021              /**
18022               * @ngdoc method
18023               * @name $timeout#cancel
18024               *
18025               * @description
18026               * Cancels a task associated with the `promise`. As a result of this, the promise will be
18027               * resolved with a rejection.
18028               *
18029               * @param {Promise=} promise Promise returned by the `$timeout` function.
18030               * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
18031               *   canceled.
18032               */
18033             timeout.cancel = function(promise) {
18034               if (promise && promise.$$timeoutId in deferreds) {
18035                 deferreds[promise.$$timeoutId].reject('canceled');
18036                 delete deferreds[promise.$$timeoutId];
18037                 return $browser.defer.cancel(promise.$$timeoutId);
18038               }
18039               return false;
18040             };
18041
18042             return timeout;
18043           }];
18044         }
18045
18046         // NOTE:  The usage of window and document instead of $window and $document here is
18047         // deliberate.  This service depends on the specific behavior of anchor nodes created by the
18048         // browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
18049         // cause us to break tests.  In addition, when the browser resolves a URL for XHR, it
18050         // doesn't know about mocked locations and resolves URLs to the real document - which is
18051         // exactly the behavior needed here.  There is little value is mocking these out for this
18052         // service.
18053         var urlParsingNode = document.createElement("a");
18054         var originUrl = urlResolve(window.location.href);
18055
18056
18057         /**
18058          *
18059          * Implementation Notes for non-IE browsers
18060          * ----------------------------------------
18061          * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
18062          * results both in the normalizing and parsing of the URL.  Normalizing means that a relative
18063          * URL will be resolved into an absolute URL in the context of the application document.
18064          * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
18065          * properties are all populated to reflect the normalized URL.  This approach has wide
18066          * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See
18067          * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
18068          *
18069          * Implementation Notes for IE
18070          * ---------------------------
18071          * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
18072          * browsers.  However, the parsed components will not be set if the URL assigned did not specify
18073          * them.  (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.)  We
18074          * work around that by performing the parsing in a 2nd step by taking a previously normalized
18075          * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the
18076          * properties such as protocol, hostname, port, etc.
18077          *
18078          * References:
18079          *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
18080          *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
18081          *   http://url.spec.whatwg.org/#urlutils
18082          *   https://github.com/angular/angular.js/pull/2902
18083          *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
18084          *
18085          * @kind function
18086          * @param {string} url The URL to be parsed.
18087          * @description Normalizes and parses a URL.
18088          * @returns {object} Returns the normalized URL as a dictionary.
18089          *
18090          *   | member name   | Description    |
18091          *   |---------------|----------------|
18092          *   | href          | A normalized version of the provided URL if it was not an absolute URL |
18093          *   | protocol      | The protocol including the trailing colon                              |
18094          *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |
18095          *   | search        | The search params, minus the question mark                             |
18096          *   | hash          | The hash string, minus the hash symbol
18097          *   | hostname      | The hostname
18098          *   | port          | The port, without ":"
18099          *   | pathname      | The pathname, beginning with "/"
18100          *
18101          */
18102         function urlResolve(url) {
18103           var href = url;
18104
18105           if (msie) {
18106             // Normalize before parse.  Refer Implementation Notes on why this is
18107             // done in two steps on IE.
18108             urlParsingNode.setAttribute("href", href);
18109             href = urlParsingNode.href;
18110           }
18111
18112           urlParsingNode.setAttribute('href', href);
18113
18114           // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
18115           return {
18116             href: urlParsingNode.href,
18117             protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
18118             host: urlParsingNode.host,
18119             search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
18120             hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
18121             hostname: urlParsingNode.hostname,
18122             port: urlParsingNode.port,
18123             pathname: (urlParsingNode.pathname.charAt(0) === '/')
18124               ? urlParsingNode.pathname
18125               : '/' + urlParsingNode.pathname
18126           };
18127         }
18128
18129         /**
18130          * Parse a request URL and determine whether this is a same-origin request as the application document.
18131          *
18132          * @param {string|object} requestUrl The url of the request as a string that will be resolved
18133          * or a parsed URL object.
18134          * @returns {boolean} Whether the request is for the same origin as the application document.
18135          */
18136         function urlIsSameOrigin(requestUrl) {
18137           var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
18138           return (parsed.protocol === originUrl.protocol &&
18139                   parsed.host === originUrl.host);
18140         }
18141
18142         /**
18143          * @ngdoc service
18144          * @name $window
18145          *
18146          * @description
18147          * A reference to the browser's `window` object. While `window`
18148          * is globally available in JavaScript, it causes testability problems, because
18149          * it is a global variable. In angular we always refer to it through the
18150          * `$window` service, so it may be overridden, removed or mocked for testing.
18151          *
18152          * Expressions, like the one defined for the `ngClick` directive in the example
18153          * below, are evaluated with respect to the current scope.  Therefore, there is
18154          * no risk of inadvertently coding in a dependency on a global value in such an
18155          * expression.
18156          *
18157          * @example
18158            <example module="windowExample">
18159              <file name="index.html">
18160                <script>
18161                  angular.module('windowExample', [])
18162                    .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
18163                      $scope.greeting = 'Hello, World!';
18164                      $scope.doGreeting = function(greeting) {
18165                        $window.alert(greeting);
18166                      };
18167                    }]);
18168                </script>
18169                <div ng-controller="ExampleController">
18170                  <input type="text" ng-model="greeting" aria-label="greeting" />
18171                  <button ng-click="doGreeting(greeting)">ALERT</button>
18172                </div>
18173              </file>
18174              <file name="protractor.js" type="protractor">
18175               it('should display the greeting in the input box', function() {
18176                element(by.model('greeting')).sendKeys('Hello, E2E Tests');
18177                // If we click the button it will block the test runner
18178                // element(':button').click();
18179               });
18180              </file>
18181            </example>
18182          */
18183         function $WindowProvider() {
18184           this.$get = valueFn(window);
18185         }
18186
18187         /**
18188          * @name $$cookieReader
18189          * @requires $document
18190          *
18191          * @description
18192          * This is a private service for reading cookies used by $http and ngCookies
18193          *
18194          * @return {Object} a key/value map of the current cookies
18195          */
18196         function $$CookieReader($document) {
18197           var rawDocument = $document[0] || {};
18198           var lastCookies = {};
18199           var lastCookieString = '';
18200
18201           function safeDecodeURIComponent(str) {
18202             try {
18203               return decodeURIComponent(str);
18204             } catch (e) {
18205               return str;
18206             }
18207           }
18208
18209           return function() {
18210             var cookieArray, cookie, i, index, name;
18211             var currentCookieString = rawDocument.cookie || '';
18212
18213             if (currentCookieString !== lastCookieString) {
18214               lastCookieString = currentCookieString;
18215               cookieArray = lastCookieString.split('; ');
18216               lastCookies = {};
18217
18218               for (i = 0; i < cookieArray.length; i++) {
18219                 cookie = cookieArray[i];
18220                 index = cookie.indexOf('=');
18221                 if (index > 0) { //ignore nameless cookies
18222                   name = safeDecodeURIComponent(cookie.substring(0, index));
18223                   // the first value that is seen for a cookie is the most
18224                   // specific one.  values for the same cookie name that
18225                   // follow are for less specific paths.
18226                   if (isUndefined(lastCookies[name])) {
18227                     lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
18228                   }
18229                 }
18230               }
18231             }
18232             return lastCookies;
18233           };
18234         }
18235
18236         $$CookieReader.$inject = ['$document'];
18237
18238         function $$CookieReaderProvider() {
18239           this.$get = $$CookieReader;
18240         }
18241
18242         /* global currencyFilter: true,
18243          dateFilter: true,
18244          filterFilter: true,
18245          jsonFilter: true,
18246          limitToFilter: true,
18247          lowercaseFilter: true,
18248          numberFilter: true,
18249          orderByFilter: true,
18250          uppercaseFilter: true,
18251          */
18252
18253         /**
18254          * @ngdoc provider
18255          * @name $filterProvider
18256          * @description
18257          *
18258          * Filters are just functions which transform input to an output. However filters need to be
18259          * Dependency Injected. To achieve this a filter definition consists of a factory function which is
18260          * annotated with dependencies and is responsible for creating a filter function.
18261          *
18262          * <div class="alert alert-warning">
18263          * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
18264          * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
18265          * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
18266          * (`myapp_subsection_filterx`).
18267          * </div>
18268          *
18269          * ```js
18270          *   // Filter registration
18271          *   function MyModule($provide, $filterProvider) {
18272          *     // create a service to demonstrate injection (not always needed)
18273          *     $provide.value('greet', function(name){
18274          *       return 'Hello ' + name + '!';
18275          *     });
18276          *
18277          *     // register a filter factory which uses the
18278          *     // greet service to demonstrate DI.
18279          *     $filterProvider.register('greet', function(greet){
18280          *       // return the filter function which uses the greet service
18281          *       // to generate salutation
18282          *       return function(text) {
18283          *         // filters need to be forgiving so check input validity
18284          *         return text && greet(text) || text;
18285          *       };
18286          *     });
18287          *   }
18288          * ```
18289          *
18290          * The filter function is registered with the `$injector` under the filter name suffix with
18291          * `Filter`.
18292          *
18293          * ```js
18294          *   it('should be the same instance', inject(
18295          *     function($filterProvider) {
18296          *       $filterProvider.register('reverse', function(){
18297          *         return ...;
18298          *       });
18299          *     },
18300          *     function($filter, reverseFilter) {
18301          *       expect($filter('reverse')).toBe(reverseFilter);
18302          *     });
18303          * ```
18304          *
18305          *
18306          * For more information about how angular filters work, and how to create your own filters, see
18307          * {@link guide/filter Filters} in the Angular Developer Guide.
18308          */
18309
18310         /**
18311          * @ngdoc service
18312          * @name $filter
18313          * @kind function
18314          * @description
18315          * Filters are used for formatting data displayed to the user.
18316          *
18317          * The general syntax in templates is as follows:
18318          *
18319          *         {{ expression [| filter_name[:parameter_value] ... ] }}
18320          *
18321          * @param {String} name Name of the filter function to retrieve
18322          * @return {Function} the filter function
18323          * @example
18324            <example name="$filter" module="filterExample">
18325              <file name="index.html">
18326                <div ng-controller="MainCtrl">
18327                 <h3>{{ originalText }}</h3>
18328                 <h3>{{ filteredText }}</h3>
18329                </div>
18330              </file>
18331
18332              <file name="script.js">
18333               angular.module('filterExample', [])
18334               .controller('MainCtrl', function($scope, $filter) {
18335                 $scope.originalText = 'hello';
18336                 $scope.filteredText = $filter('uppercase')($scope.originalText);
18337               });
18338              </file>
18339            </example>
18340           */
18341         $FilterProvider.$inject = ['$provide'];
18342         function $FilterProvider($provide) {
18343           var suffix = 'Filter';
18344
18345           /**
18346            * @ngdoc method
18347            * @name $filterProvider#register
18348            * @param {string|Object} name Name of the filter function, or an object map of filters where
18349            *    the keys are the filter names and the values are the filter factories.
18350            *
18351            *    <div class="alert alert-warning">
18352            *    **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
18353            *    Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
18354            *    your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
18355            *    (`myapp_subsection_filterx`).
18356            *    </div>
18357             * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered.
18358            * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
18359            *    of the registered filter instances.
18360            */
18361           function register(name, factory) {
18362             if (isObject(name)) {
18363               var filters = {};
18364               forEach(name, function(filter, key) {
18365                 filters[key] = register(key, filter);
18366               });
18367               return filters;
18368             } else {
18369               return $provide.factory(name + suffix, factory);
18370             }
18371           }
18372           this.register = register;
18373
18374           this.$get = ['$injector', function($injector) {
18375             return function(name) {
18376               return $injector.get(name + suffix);
18377             };
18378           }];
18379
18380           ////////////////////////////////////////
18381
18382           /* global
18383             currencyFilter: false,
18384             dateFilter: false,
18385             filterFilter: false,
18386             jsonFilter: false,
18387             limitToFilter: false,
18388             lowercaseFilter: false,
18389             numberFilter: false,
18390             orderByFilter: false,
18391             uppercaseFilter: false,
18392           */
18393
18394           register('currency', currencyFilter);
18395           register('date', dateFilter);
18396           register('filter', filterFilter);
18397           register('json', jsonFilter);
18398           register('limitTo', limitToFilter);
18399           register('lowercase', lowercaseFilter);
18400           register('number', numberFilter);
18401           register('orderBy', orderByFilter);
18402           register('uppercase', uppercaseFilter);
18403         }
18404
18405         /**
18406          * @ngdoc filter
18407          * @name filter
18408          * @kind function
18409          *
18410          * @description
18411          * Selects a subset of items from `array` and returns it as a new array.
18412          *
18413          * @param {Array} array The source array.
18414          * @param {string|Object|function()} expression The predicate to be used for selecting items from
18415          *   `array`.
18416          *
18417          *   Can be one of:
18418          *
18419          *   - `string`: The string is used for matching against the contents of the `array`. All strings or
18420          *     objects with string properties in `array` that match this string will be returned. This also
18421          *     applies to nested object properties.
18422          *     The predicate can be negated by prefixing the string with `!`.
18423          *
18424          *   - `Object`: A pattern object can be used to filter specific properties on objects contained
18425          *     by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
18426          *     which have property `name` containing "M" and property `phone` containing "1". A special
18427          *     property name `$` can be used (as in `{$:"text"}`) to accept a match against any
18428          *     property of the object or its nested object properties. That's equivalent to the simple
18429          *     substring match with a `string` as described above. The predicate can be negated by prefixing
18430          *     the string with `!`.
18431          *     For example `{name: "!M"}` predicate will return an array of items which have property `name`
18432          *     not containing "M".
18433          *
18434          *     Note that a named property will match properties on the same level only, while the special
18435          *     `$` property will match properties on the same level or deeper. E.g. an array item like
18436          *     `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
18437          *     **will** be matched by `{$: 'John'}`.
18438          *
18439          *   - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.
18440          *     The function is called for each element of the array, with the element, its index, and
18441          *     the entire array itself as arguments.
18442          *
18443          *     The final result is an array of those elements that the predicate returned true for.
18444          *
18445          * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
18446          *     determining if the expected value (from the filter expression) and actual value (from
18447          *     the object in the array) should be considered a match.
18448          *
18449          *   Can be one of:
18450          *
18451          *   - `function(actual, expected)`:
18452          *     The function will be given the object value and the predicate value to compare and
18453          *     should return true if both values should be considered equal.
18454          *
18455          *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
18456          *     This is essentially strict comparison of expected and actual.
18457          *
18458          *   - `false|undefined`: A short hand for a function which will look for a substring match in case
18459          *     insensitive way.
18460          *
18461          *     Primitive values are converted to strings. Objects are not compared against primitives,
18462          *     unless they have a custom `toString` method (e.g. `Date` objects).
18463          *
18464          * @example
18465            <example>
18466              <file name="index.html">
18467                <div ng-init="friends = [{name:'John', phone:'555-1276'},
18468                                         {name:'Mary', phone:'800-BIG-MARY'},
18469                                         {name:'Mike', phone:'555-4321'},
18470                                         {name:'Adam', phone:'555-5678'},
18471                                         {name:'Julie', phone:'555-8765'},
18472                                         {name:'Juliette', phone:'555-5678'}]"></div>
18473
18474                <label>Search: <input ng-model="searchText"></label>
18475                <table id="searchTextResults">
18476                  <tr><th>Name</th><th>Phone</th></tr>
18477                  <tr ng-repeat="friend in friends | filter:searchText">
18478                    <td>{{friend.name}}</td>
18479                    <td>{{friend.phone}}</td>
18480                  </tr>
18481                </table>
18482                <hr>
18483                <label>Any: <input ng-model="search.$"></label> <br>
18484                <label>Name only <input ng-model="search.name"></label><br>
18485                <label>Phone only <input ng-model="search.phone"></label><br>
18486                <label>Equality <input type="checkbox" ng-model="strict"></label><br>
18487                <table id="searchObjResults">
18488                  <tr><th>Name</th><th>Phone</th></tr>
18489                  <tr ng-repeat="friendObj in friends | filter:search:strict">
18490                    <td>{{friendObj.name}}</td>
18491                    <td>{{friendObj.phone}}</td>
18492                  </tr>
18493                </table>
18494              </file>
18495              <file name="protractor.js" type="protractor">
18496                var expectFriendNames = function(expectedNames, key) {
18497                  element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
18498                    arr.forEach(function(wd, i) {
18499                      expect(wd.getText()).toMatch(expectedNames[i]);
18500                    });
18501                  });
18502                };
18503
18504                it('should search across all fields when filtering with a string', function() {
18505                  var searchText = element(by.model('searchText'));
18506                  searchText.clear();
18507                  searchText.sendKeys('m');
18508                  expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
18509
18510                  searchText.clear();
18511                  searchText.sendKeys('76');
18512                  expectFriendNames(['John', 'Julie'], 'friend');
18513                });
18514
18515                it('should search in specific fields when filtering with a predicate object', function() {
18516                  var searchAny = element(by.model('search.$'));
18517                  searchAny.clear();
18518                  searchAny.sendKeys('i');
18519                  expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
18520                });
18521                it('should use a equal comparison when comparator is true', function() {
18522                  var searchName = element(by.model('search.name'));
18523                  var strict = element(by.model('strict'));
18524                  searchName.clear();
18525                  searchName.sendKeys('Julie');
18526                  strict.click();
18527                  expectFriendNames(['Julie'], 'friendObj');
18528                });
18529              </file>
18530            </example>
18531          */
18532         function filterFilter() {
18533           return function(array, expression, comparator) {
18534             if (!isArrayLike(array)) {
18535               if (array == null) {
18536                 return array;
18537               } else {
18538                 throw minErr('filter')('notarray', 'Expected array but received: {0}', array);
18539               }
18540             }
18541
18542             var expressionType = getTypeForFilter(expression);
18543             var predicateFn;
18544             var matchAgainstAnyProp;
18545
18546             switch (expressionType) {
18547               case 'function':
18548                 predicateFn = expression;
18549                 break;
18550               case 'boolean':
18551               case 'null':
18552               case 'number':
18553               case 'string':
18554                 matchAgainstAnyProp = true;
18555                 //jshint -W086
18556               case 'object':
18557                 //jshint +W086
18558                 predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
18559                 break;
18560               default:
18561                 return array;
18562             }
18563
18564             return Array.prototype.filter.call(array, predicateFn);
18565           };
18566         }
18567
18568         // Helper functions for `filterFilter`
18569         function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
18570           var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
18571           var predicateFn;
18572
18573           if (comparator === true) {
18574             comparator = equals;
18575           } else if (!isFunction(comparator)) {
18576             comparator = function(actual, expected) {
18577               if (isUndefined(actual)) {
18578                 // No substring matching against `undefined`
18579                 return false;
18580               }
18581               if ((actual === null) || (expected === null)) {
18582                 // No substring matching against `null`; only match against `null`
18583                 return actual === expected;
18584               }
18585               if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) {
18586                 // Should not compare primitives against objects, unless they have custom `toString` method
18587                 return false;
18588               }
18589
18590               actual = lowercase('' + actual);
18591               expected = lowercase('' + expected);
18592               return actual.indexOf(expected) !== -1;
18593             };
18594           }
18595
18596           predicateFn = function(item) {
18597             if (shouldMatchPrimitives && !isObject(item)) {
18598               return deepCompare(item, expression.$, comparator, false);
18599             }
18600             return deepCompare(item, expression, comparator, matchAgainstAnyProp);
18601           };
18602
18603           return predicateFn;
18604         }
18605
18606         function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
18607           var actualType = getTypeForFilter(actual);
18608           var expectedType = getTypeForFilter(expected);
18609
18610           if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
18611             return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
18612           } else if (isArray(actual)) {
18613             // In case `actual` is an array, consider it a match
18614             // if ANY of it's items matches `expected`
18615             return actual.some(function(item) {
18616               return deepCompare(item, expected, comparator, matchAgainstAnyProp);
18617             });
18618           }
18619
18620           switch (actualType) {
18621             case 'object':
18622               var key;
18623               if (matchAgainstAnyProp) {
18624                 for (key in actual) {
18625                   if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
18626                     return true;
18627                   }
18628                 }
18629                 return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
18630               } else if (expectedType === 'object') {
18631                 for (key in expected) {
18632                   var expectedVal = expected[key];
18633                   if (isFunction(expectedVal) || isUndefined(expectedVal)) {
18634                     continue;
18635                   }
18636
18637                   var matchAnyProperty = key === '$';
18638                   var actualVal = matchAnyProperty ? actual : actual[key];
18639                   if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
18640                     return false;
18641                   }
18642                 }
18643                 return true;
18644               } else {
18645                 return comparator(actual, expected);
18646               }
18647               break;
18648             case 'function':
18649               return false;
18650             default:
18651               return comparator(actual, expected);
18652           }
18653         }
18654
18655         // Used for easily differentiating between `null` and actual `object`
18656         function getTypeForFilter(val) {
18657           return (val === null) ? 'null' : typeof val;
18658         }
18659
18660         /**
18661          * @ngdoc filter
18662          * @name currency
18663          * @kind function
18664          *
18665          * @description
18666          * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
18667          * symbol for current locale is used.
18668          *
18669          * @param {number} amount Input to filter.
18670          * @param {string=} symbol Currency symbol or identifier to be displayed.
18671          * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale
18672          * @returns {string} Formatted number.
18673          *
18674          *
18675          * @example
18676            <example module="currencyExample">
18677              <file name="index.html">
18678                <script>
18679                  angular.module('currencyExample', [])
18680                    .controller('ExampleController', ['$scope', function($scope) {
18681                      $scope.amount = 1234.56;
18682                    }]);
18683                </script>
18684                <div ng-controller="ExampleController">
18685                  <input type="number" ng-model="amount" aria-label="amount"> <br>
18686                  default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
18687                  custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span>
18688                  no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span>
18689                </div>
18690              </file>
18691              <file name="protractor.js" type="protractor">
18692                it('should init with 1234.56', function() {
18693                  expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
18694                  expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');
18695                  expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');
18696                });
18697                it('should update', function() {
18698                  if (browser.params.browser == 'safari') {
18699                    // Safari does not understand the minus key. See
18700                    // https://github.com/angular/protractor/issues/481
18701                    return;
18702                  }
18703                  element(by.model('amount')).clear();
18704                  element(by.model('amount')).sendKeys('-1234');
18705                  expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00');
18706                  expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00');
18707                  expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234');
18708                });
18709              </file>
18710            </example>
18711          */
18712         currencyFilter.$inject = ['$locale'];
18713         function currencyFilter($locale) {
18714           var formats = $locale.NUMBER_FORMATS;
18715           return function(amount, currencySymbol, fractionSize) {
18716             if (isUndefined(currencySymbol)) {
18717               currencySymbol = formats.CURRENCY_SYM;
18718             }
18719
18720             if (isUndefined(fractionSize)) {
18721               fractionSize = formats.PATTERNS[1].maxFrac;
18722             }
18723
18724             // if null or undefined pass it through
18725             return (amount == null)
18726                 ? amount
18727                 : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
18728                     replace(/\u00A4/g, currencySymbol);
18729           };
18730         }
18731
18732         /**
18733          * @ngdoc filter
18734          * @name number
18735          * @kind function
18736          *
18737          * @description
18738          * Formats a number as text.
18739          *
18740          * If the input is null or undefined, it will just be returned.
18741          * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
18742          * If the input is not a number an empty string is returned.
18743          *
18744          *
18745          * @param {number|string} number Number to format.
18746          * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
18747          * If this is not provided then the fraction size is computed from the current locale's number
18748          * formatting pattern. In the case of the default locale, it will be 3.
18749          * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
18750          *
18751          * @example
18752            <example module="numberFilterExample">
18753              <file name="index.html">
18754                <script>
18755                  angular.module('numberFilterExample', [])
18756                    .controller('ExampleController', ['$scope', function($scope) {
18757                      $scope.val = 1234.56789;
18758                    }]);
18759                </script>
18760                <div ng-controller="ExampleController">
18761                  <label>Enter number: <input ng-model='val'></label><br>
18762                  Default formatting: <span id='number-default'>{{val | number}}</span><br>
18763                  No fractions: <span>{{val | number:0}}</span><br>
18764                  Negative number: <span>{{-val | number:4}}</span>
18765                </div>
18766              </file>
18767              <file name="protractor.js" type="protractor">
18768                it('should format numbers', function() {
18769                  expect(element(by.id('number-default')).getText()).toBe('1,234.568');
18770                  expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
18771                  expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
18772                });
18773
18774                it('should update', function() {
18775                  element(by.model('val')).clear();
18776                  element(by.model('val')).sendKeys('3374.333');
18777                  expect(element(by.id('number-default')).getText()).toBe('3,374.333');
18778                  expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
18779                  expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
18780               });
18781              </file>
18782            </example>
18783          */
18784
18785
18786         numberFilter.$inject = ['$locale'];
18787         function numberFilter($locale) {
18788           var formats = $locale.NUMBER_FORMATS;
18789           return function(number, fractionSize) {
18790
18791             // if null or undefined pass it through
18792             return (number == null)
18793                 ? number
18794                 : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
18795                                fractionSize);
18796           };
18797         }
18798
18799         var DECIMAL_SEP = '.';
18800         function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
18801           if (isObject(number)) return '';
18802
18803           var isNegative = number < 0;
18804           number = Math.abs(number);
18805
18806           var isInfinity = number === Infinity;
18807           if (!isInfinity && !isFinite(number)) return '';
18808
18809           var numStr = number + '',
18810               formatedText = '',
18811               hasExponent = false,
18812               parts = [];
18813
18814           if (isInfinity) formatedText = '\u221e';
18815
18816           if (!isInfinity && numStr.indexOf('e') !== -1) {
18817             var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
18818             if (match && match[2] == '-' && match[3] > fractionSize + 1) {
18819               number = 0;
18820             } else {
18821               formatedText = numStr;
18822               hasExponent = true;
18823             }
18824           }
18825
18826           if (!isInfinity && !hasExponent) {
18827             var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
18828
18829             // determine fractionSize if it is not specified
18830             if (isUndefined(fractionSize)) {
18831               fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
18832             }
18833
18834             // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
18835             // inspired by:
18836             // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
18837             number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
18838
18839             var fraction = ('' + number).split(DECIMAL_SEP);
18840             var whole = fraction[0];
18841             fraction = fraction[1] || '';
18842
18843             var i, pos = 0,
18844                 lgroup = pattern.lgSize,
18845                 group = pattern.gSize;
18846
18847             if (whole.length >= (lgroup + group)) {
18848               pos = whole.length - lgroup;
18849               for (i = 0; i < pos; i++) {
18850                 if ((pos - i) % group === 0 && i !== 0) {
18851                   formatedText += groupSep;
18852                 }
18853                 formatedText += whole.charAt(i);
18854               }
18855             }
18856
18857             for (i = pos; i < whole.length; i++) {
18858               if ((whole.length - i) % lgroup === 0 && i !== 0) {
18859                 formatedText += groupSep;
18860               }
18861               formatedText += whole.charAt(i);
18862             }
18863
18864             // format fraction part.
18865             while (fraction.length < fractionSize) {
18866               fraction += '0';
18867             }
18868
18869             if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
18870           } else {
18871             if (fractionSize > 0 && number < 1) {
18872               formatedText = number.toFixed(fractionSize);
18873               number = parseFloat(formatedText);
18874               formatedText = formatedText.replace(DECIMAL_SEP, decimalSep);
18875             }
18876           }
18877
18878           if (number === 0) {
18879             isNegative = false;
18880           }
18881
18882           parts.push(isNegative ? pattern.negPre : pattern.posPre,
18883                      formatedText,
18884                      isNegative ? pattern.negSuf : pattern.posSuf);
18885           return parts.join('');
18886         }
18887
18888         function padNumber(num, digits, trim) {
18889           var neg = '';
18890           if (num < 0) {
18891             neg =  '-';
18892             num = -num;
18893           }
18894           num = '' + num;
18895           while (num.length < digits) num = '0' + num;
18896           if (trim) {
18897             num = num.substr(num.length - digits);
18898           }
18899           return neg + num;
18900         }
18901
18902
18903         function dateGetter(name, size, offset, trim) {
18904           offset = offset || 0;
18905           return function(date) {
18906             var value = date['get' + name]();
18907             if (offset > 0 || value > -offset) {
18908               value += offset;
18909             }
18910             if (value === 0 && offset == -12) value = 12;
18911             return padNumber(value, size, trim);
18912           };
18913         }
18914
18915         function dateStrGetter(name, shortForm) {
18916           return function(date, formats) {
18917             var value = date['get' + name]();
18918             var get = uppercase(shortForm ? ('SHORT' + name) : name);
18919
18920             return formats[get][value];
18921           };
18922         }
18923
18924         function timeZoneGetter(date, formats, offset) {
18925           var zone = -1 * offset;
18926           var paddedZone = (zone >= 0) ? "+" : "";
18927
18928           paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
18929                         padNumber(Math.abs(zone % 60), 2);
18930
18931           return paddedZone;
18932         }
18933
18934         function getFirstThursdayOfYear(year) {
18935             // 0 = index of January
18936             var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
18937             // 4 = index of Thursday (+1 to account for 1st = 5)
18938             // 11 = index of *next* Thursday (+1 account for 1st = 12)
18939             return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
18940         }
18941
18942         function getThursdayThisWeek(datetime) {
18943             return new Date(datetime.getFullYear(), datetime.getMonth(),
18944               // 4 = index of Thursday
18945               datetime.getDate() + (4 - datetime.getDay()));
18946         }
18947
18948         function weekGetter(size) {
18949            return function(date) {
18950               var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
18951                  thisThurs = getThursdayThisWeek(date);
18952
18953               var diff = +thisThurs - +firstThurs,
18954                  result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
18955
18956               return padNumber(result, size);
18957            };
18958         }
18959
18960         function ampmGetter(date, formats) {
18961           return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
18962         }
18963
18964         function eraGetter(date, formats) {
18965           return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
18966         }
18967
18968         function longEraGetter(date, formats) {
18969           return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
18970         }
18971
18972         var DATE_FORMATS = {
18973           yyyy: dateGetter('FullYear', 4),
18974             yy: dateGetter('FullYear', 2, 0, true),
18975              y: dateGetter('FullYear', 1),
18976           MMMM: dateStrGetter('Month'),
18977            MMM: dateStrGetter('Month', true),
18978             MM: dateGetter('Month', 2, 1),
18979              M: dateGetter('Month', 1, 1),
18980             dd: dateGetter('Date', 2),
18981              d: dateGetter('Date', 1),
18982             HH: dateGetter('Hours', 2),
18983              H: dateGetter('Hours', 1),
18984             hh: dateGetter('Hours', 2, -12),
18985              h: dateGetter('Hours', 1, -12),
18986             mm: dateGetter('Minutes', 2),
18987              m: dateGetter('Minutes', 1),
18988             ss: dateGetter('Seconds', 2),
18989              s: dateGetter('Seconds', 1),
18990              // while ISO 8601 requires fractions to be prefixed with `.` or `,`
18991              // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
18992            sss: dateGetter('Milliseconds', 3),
18993           EEEE: dateStrGetter('Day'),
18994            EEE: dateStrGetter('Day', true),
18995              a: ampmGetter,
18996              Z: timeZoneGetter,
18997             ww: weekGetter(2),
18998              w: weekGetter(1),
18999              G: eraGetter,
19000              GG: eraGetter,
19001              GGG: eraGetter,
19002              GGGG: longEraGetter
19003         };
19004
19005         var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
19006             NUMBER_STRING = /^\-?\d+$/;
19007
19008         /**
19009          * @ngdoc filter
19010          * @name date
19011          * @kind function
19012          *
19013          * @description
19014          *   Formats `date` to a string based on the requested `format`.
19015          *
19016          *   `format` string can be composed of the following elements:
19017          *
19018          *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
19019          *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
19020          *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
19021          *   * `'MMMM'`: Month in year (January-December)
19022          *   * `'MMM'`: Month in year (Jan-Dec)
19023          *   * `'MM'`: Month in year, padded (01-12)
19024          *   * `'M'`: Month in year (1-12)
19025          *   * `'dd'`: Day in month, padded (01-31)
19026          *   * `'d'`: Day in month (1-31)
19027          *   * `'EEEE'`: Day in Week,(Sunday-Saturday)
19028          *   * `'EEE'`: Day in Week, (Sun-Sat)
19029          *   * `'HH'`: Hour in day, padded (00-23)
19030          *   * `'H'`: Hour in day (0-23)
19031          *   * `'hh'`: Hour in AM/PM, padded (01-12)
19032          *   * `'h'`: Hour in AM/PM, (1-12)
19033          *   * `'mm'`: Minute in hour, padded (00-59)
19034          *   * `'m'`: Minute in hour (0-59)
19035          *   * `'ss'`: Second in minute, padded (00-59)
19036          *   * `'s'`: Second in minute (0-59)
19037          *   * `'sss'`: Millisecond in second, padded (000-999)
19038          *   * `'a'`: AM/PM marker
19039          *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
19040          *   * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
19041          *   * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
19042          *   * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
19043          *   * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
19044          *
19045          *   `format` string can also be one of the following predefined
19046          *   {@link guide/i18n localizable formats}:
19047          *
19048          *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
19049          *     (e.g. Sep 3, 2010 12:05:08 PM)
19050          *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 PM)
19051          *   * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US  locale
19052          *     (e.g. Friday, September 3, 2010)
19053          *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)
19054          *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)
19055          *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
19056          *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)
19057          *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)
19058          *
19059          *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
19060          *   `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
19061          *   (e.g. `"h 'o''clock'"`).
19062          *
19063          * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
19064          *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
19065          *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
19066          *    specified in the string input, the time is considered to be in the local timezone.
19067          * @param {string=} format Formatting rules (see Description). If not specified,
19068          *    `mediumDate` is used.
19069          * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the
19070          *    continental US time zone abbreviations, but for general use, use a time zone offset, for
19071          *    example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
19072          *    If not specified, the timezone of the browser will be used.
19073          * @returns {string} Formatted string or the input if input is not recognized as date/millis.
19074          *
19075          * @example
19076            <example>
19077              <file name="index.html">
19078                <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
19079                    <span>{{1288323623006 | date:'medium'}}</span><br>
19080                <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
19081                   <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
19082                <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
19083                   <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
19084                <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
19085                   <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
19086              </file>
19087              <file name="protractor.js" type="protractor">
19088                it('should format date', function() {
19089                  expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
19090                     toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
19091                  expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
19092                     toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
19093                  expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
19094                     toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
19095                  expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
19096                     toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
19097                });
19098              </file>
19099            </example>
19100          */
19101         dateFilter.$inject = ['$locale'];
19102         function dateFilter($locale) {
19103
19104
19105           var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
19106                              // 1        2       3         4          5          6          7          8  9     10      11
19107           function jsonStringToDate(string) {
19108             var match;
19109             if (match = string.match(R_ISO8601_STR)) {
19110               var date = new Date(0),
19111                   tzHour = 0,
19112                   tzMin  = 0,
19113                   dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
19114                   timeSetter = match[8] ? date.setUTCHours : date.setHours;
19115
19116               if (match[9]) {
19117                 tzHour = toInt(match[9] + match[10]);
19118                 tzMin = toInt(match[9] + match[11]);
19119               }
19120               dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
19121               var h = toInt(match[4] || 0) - tzHour;
19122               var m = toInt(match[5] || 0) - tzMin;
19123               var s = toInt(match[6] || 0);
19124               var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
19125               timeSetter.call(date, h, m, s, ms);
19126               return date;
19127             }
19128             return string;
19129           }
19130
19131
19132           return function(date, format, timezone) {
19133             var text = '',
19134                 parts = [],
19135                 fn, match;
19136
19137             format = format || 'mediumDate';
19138             format = $locale.DATETIME_FORMATS[format] || format;
19139             if (isString(date)) {
19140               date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date);
19141             }
19142
19143             if (isNumber(date)) {
19144               date = new Date(date);
19145             }
19146
19147             if (!isDate(date) || !isFinite(date.getTime())) {
19148               return date;
19149             }
19150
19151             while (format) {
19152               match = DATE_FORMATS_SPLIT.exec(format);
19153               if (match) {
19154                 parts = concat(parts, match, 1);
19155                 format = parts.pop();
19156               } else {
19157                 parts.push(format);
19158                 format = null;
19159               }
19160             }
19161
19162             var dateTimezoneOffset = date.getTimezoneOffset();
19163             if (timezone) {
19164               dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
19165               date = convertTimezoneToLocal(date, timezone, true);
19166             }
19167             forEach(parts, function(value) {
19168               fn = DATE_FORMATS[value];
19169               text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)
19170                          : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
19171             });
19172
19173             return text;
19174           };
19175         }
19176
19177
19178         /**
19179          * @ngdoc filter
19180          * @name json
19181          * @kind function
19182          *
19183          * @description
19184          *   Allows you to convert a JavaScript object into JSON string.
19185          *
19186          *   This filter is mostly useful for debugging. When using the double curly {{value}} notation
19187          *   the binding is automatically converted to JSON.
19188          *
19189          * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
19190          * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
19191          * @returns {string} JSON string.
19192          *
19193          *
19194          * @example
19195            <example>
19196              <file name="index.html">
19197                <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
19198                <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
19199              </file>
19200              <file name="protractor.js" type="protractor">
19201                it('should jsonify filtered objects', function() {
19202                  expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n  "name": ?"value"\n}/);
19203                  expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n    "name": ?"value"\n}/);
19204                });
19205              </file>
19206            </example>
19207          *
19208          */
19209         function jsonFilter() {
19210           return function(object, spacing) {
19211             if (isUndefined(spacing)) {
19212                 spacing = 2;
19213             }
19214             return toJson(object, spacing);
19215           };
19216         }
19217
19218
19219         /**
19220          * @ngdoc filter
19221          * @name lowercase
19222          * @kind function
19223          * @description
19224          * Converts string to lowercase.
19225          * @see angular.lowercase
19226          */
19227         var lowercaseFilter = valueFn(lowercase);
19228
19229
19230         /**
19231          * @ngdoc filter
19232          * @name uppercase
19233          * @kind function
19234          * @description
19235          * Converts string to uppercase.
19236          * @see angular.uppercase
19237          */
19238         var uppercaseFilter = valueFn(uppercase);
19239
19240         /**
19241          * @ngdoc filter
19242          * @name limitTo
19243          * @kind function
19244          *
19245          * @description
19246          * Creates a new array or string containing only a specified number of elements. The elements
19247          * are taken from either the beginning or the end of the source array, string or number, as specified by
19248          * the value and sign (positive or negative) of `limit`. If a number is used as input, it is
19249          * converted to a string.
19250          *
19251          * @param {Array|string|number} input Source array, string or number to be limited.
19252          * @param {string|number} limit The length of the returned array or string. If the `limit` number
19253          *     is positive, `limit` number of items from the beginning of the source array/string are copied.
19254          *     If the number is negative, `limit` number  of items from the end of the source array/string
19255          *     are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,
19256          *     the input will be returned unchanged.
19257          * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin`
19258          *     indicates an offset from the end of `input`. Defaults to `0`.
19259          * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
19260          *     had less than `limit` elements.
19261          *
19262          * @example
19263            <example module="limitToExample">
19264              <file name="index.html">
19265                <script>
19266                  angular.module('limitToExample', [])
19267                    .controller('ExampleController', ['$scope', function($scope) {
19268                      $scope.numbers = [1,2,3,4,5,6,7,8,9];
19269                      $scope.letters = "abcdefghi";
19270                      $scope.longNumber = 2345432342;
19271                      $scope.numLimit = 3;
19272                      $scope.letterLimit = 3;
19273                      $scope.longNumberLimit = 3;
19274                    }]);
19275                </script>
19276                <div ng-controller="ExampleController">
19277                  <label>
19278                     Limit {{numbers}} to:
19279                     <input type="number" step="1" ng-model="numLimit">
19280                  </label>
19281                  <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
19282                  <label>
19283                     Limit {{letters}} to:
19284                     <input type="number" step="1" ng-model="letterLimit">
19285                  </label>
19286                  <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
19287                  <label>
19288                     Limit {{longNumber}} to:
19289                     <input type="number" step="1" ng-model="longNumberLimit">
19290                  </label>
19291                  <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
19292                </div>
19293              </file>
19294              <file name="protractor.js" type="protractor">
19295                var numLimitInput = element(by.model('numLimit'));
19296                var letterLimitInput = element(by.model('letterLimit'));
19297                var longNumberLimitInput = element(by.model('longNumberLimit'));
19298                var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
19299                var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
19300                var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));
19301
19302                it('should limit the number array to first three items', function() {
19303                  expect(numLimitInput.getAttribute('value')).toBe('3');
19304                  expect(letterLimitInput.getAttribute('value')).toBe('3');
19305                  expect(longNumberLimitInput.getAttribute('value')).toBe('3');
19306                  expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
19307                  expect(limitedLetters.getText()).toEqual('Output letters: abc');
19308                  expect(limitedLongNumber.getText()).toEqual('Output long number: 234');
19309                });
19310
19311                // There is a bug in safari and protractor that doesn't like the minus key
19312                // it('should update the output when -3 is entered', function() {
19313                //   numLimitInput.clear();
19314                //   numLimitInput.sendKeys('-3');
19315                //   letterLimitInput.clear();
19316                //   letterLimitInput.sendKeys('-3');
19317                //   longNumberLimitInput.clear();
19318                //   longNumberLimitInput.sendKeys('-3');
19319                //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
19320                //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');
19321                //   expect(limitedLongNumber.getText()).toEqual('Output long number: 342');
19322                // });
19323
19324                it('should not exceed the maximum size of input array', function() {
19325                  numLimitInput.clear();
19326                  numLimitInput.sendKeys('100');
19327                  letterLimitInput.clear();
19328                  letterLimitInput.sendKeys('100');
19329                  longNumberLimitInput.clear();
19330                  longNumberLimitInput.sendKeys('100');
19331                  expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
19332                  expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
19333                  expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
19334                });
19335              </file>
19336            </example>
19337         */
19338         function limitToFilter() {
19339           return function(input, limit, begin) {
19340             if (Math.abs(Number(limit)) === Infinity) {
19341               limit = Number(limit);
19342             } else {
19343               limit = toInt(limit);
19344             }
19345             if (isNaN(limit)) return input;
19346
19347             if (isNumber(input)) input = input.toString();
19348             if (!isArray(input) && !isString(input)) return input;
19349
19350             begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
19351             begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;
19352
19353             if (limit >= 0) {
19354               return input.slice(begin, begin + limit);
19355             } else {
19356               if (begin === 0) {
19357                 return input.slice(limit, input.length);
19358               } else {
19359                 return input.slice(Math.max(0, begin + limit), begin);
19360               }
19361             }
19362           };
19363         }
19364
19365         /**
19366          * @ngdoc filter
19367          * @name orderBy
19368          * @kind function
19369          *
19370          * @description
19371          * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
19372          * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
19373          * as expected, make sure they are actually being saved as numbers and not strings.
19374          *
19375          * @param {Array} array The array to sort.
19376          * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
19377          *    used by the comparator to determine the order of elements.
19378          *
19379          *    Can be one of:
19380          *
19381          *    - `function`: Getter function. The result of this function will be sorted using the
19382          *      `<`, `===`, `>` operator.
19383          *    - `string`: An Angular expression. The result of this expression is used to compare elements
19384          *      (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
19385          *      3 first characters of a property called `name`). The result of a constant expression
19386          *      is interpreted as a property name to be used in comparisons (for example `"special name"`
19387          *      to sort object by the value of their `special name` property). An expression can be
19388          *      optionally prefixed with `+` or `-` to control ascending or descending sort order
19389          *      (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array
19390          *      element itself is used to compare where sorting.
19391          *    - `Array`: An array of function or string predicates. The first predicate in the array
19392          *      is used for sorting, but when two items are equivalent, the next predicate is used.
19393          *
19394          *    If the predicate is missing or empty then it defaults to `'+'`.
19395          *
19396          * @param {boolean=} reverse Reverse the order of the array.
19397          * @returns {Array} Sorted copy of the source array.
19398          *
19399          *
19400          * @example
19401          * The example below demonstrates a simple ngRepeat, where the data is sorted
19402          * by age in descending order (predicate is set to `'-age'`).
19403          * `reverse` is not set, which means it defaults to `false`.
19404            <example module="orderByExample">
19405              <file name="index.html">
19406                <script>
19407                  angular.module('orderByExample', [])
19408                    .controller('ExampleController', ['$scope', function($scope) {
19409                      $scope.friends =
19410                          [{name:'John', phone:'555-1212', age:10},
19411                           {name:'Mary', phone:'555-9876', age:19},
19412                           {name:'Mike', phone:'555-4321', age:21},
19413                           {name:'Adam', phone:'555-5678', age:35},
19414                           {name:'Julie', phone:'555-8765', age:29}];
19415                    }]);
19416                </script>
19417                <div ng-controller="ExampleController">
19418                  <table class="friend">
19419                    <tr>
19420                      <th>Name</th>
19421                      <th>Phone Number</th>
19422                      <th>Age</th>
19423                    </tr>
19424                    <tr ng-repeat="friend in friends | orderBy:'-age'">
19425                      <td>{{friend.name}}</td>
19426                      <td>{{friend.phone}}</td>
19427                      <td>{{friend.age}}</td>
19428                    </tr>
19429                  </table>
19430                </div>
19431              </file>
19432            </example>
19433          *
19434          * The predicate and reverse parameters can be controlled dynamically through scope properties,
19435          * as shown in the next example.
19436          * @example
19437            <example module="orderByExample">
19438              <file name="index.html">
19439                <script>
19440                  angular.module('orderByExample', [])
19441                    .controller('ExampleController', ['$scope', function($scope) {
19442                      $scope.friends =
19443                          [{name:'John', phone:'555-1212', age:10},
19444                           {name:'Mary', phone:'555-9876', age:19},
19445                           {name:'Mike', phone:'555-4321', age:21},
19446                           {name:'Adam', phone:'555-5678', age:35},
19447                           {name:'Julie', phone:'555-8765', age:29}];
19448                      $scope.predicate = 'age';
19449                      $scope.reverse = true;
19450                      $scope.order = function(predicate) {
19451                        $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
19452                        $scope.predicate = predicate;
19453                      };
19454                    }]);
19455                </script>
19456                <style type="text/css">
19457                  .sortorder:after {
19458                    content: '\25b2';
19459                  }
19460                  .sortorder.reverse:after {
19461                    content: '\25bc';
19462                  }
19463                </style>
19464                <div ng-controller="ExampleController">
19465                  <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
19466                  <hr/>
19467                  [ <a href="" ng-click="predicate=''">unsorted</a> ]
19468                  <table class="friend">
19469                    <tr>
19470                      <th>
19471                        <a href="" ng-click="order('name')">Name</a>
19472                        <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
19473                      </th>
19474                      <th>
19475                        <a href="" ng-click="order('phone')">Phone Number</a>
19476                        <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
19477                      </th>
19478                      <th>
19479                        <a href="" ng-click="order('age')">Age</a>
19480                        <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
19481                      </th>
19482                    </tr>
19483                    <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
19484                      <td>{{friend.name}}</td>
19485                      <td>{{friend.phone}}</td>
19486                      <td>{{friend.age}}</td>
19487                    </tr>
19488                  </table>
19489                </div>
19490              </file>
19491            </example>
19492          *
19493          * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
19494          * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
19495          * desired parameters.
19496          *
19497          * Example:
19498          *
19499          * @example
19500           <example module="orderByExample">
19501             <file name="index.html">
19502               <div ng-controller="ExampleController">
19503                 <table class="friend">
19504                   <tr>
19505                     <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
19506                       (<a href="" ng-click="order('-name',false)">^</a>)</th>
19507                     <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
19508                     <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
19509                   </tr>
19510                   <tr ng-repeat="friend in friends">
19511                     <td>{{friend.name}}</td>
19512                     <td>{{friend.phone}}</td>
19513                     <td>{{friend.age}}</td>
19514                   </tr>
19515                 </table>
19516               </div>
19517             </file>
19518
19519             <file name="script.js">
19520               angular.module('orderByExample', [])
19521                 .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
19522                   var orderBy = $filter('orderBy');
19523                   $scope.friends = [
19524                     { name: 'John',    phone: '555-1212',    age: 10 },
19525                     { name: 'Mary',    phone: '555-9876',    age: 19 },
19526                     { name: 'Mike',    phone: '555-4321',    age: 21 },
19527                     { name: 'Adam',    phone: '555-5678',    age: 35 },
19528                     { name: 'Julie',   phone: '555-8765',    age: 29 }
19529                   ];
19530                   $scope.order = function(predicate, reverse) {
19531                     $scope.friends = orderBy($scope.friends, predicate, reverse);
19532                   };
19533                   $scope.order('-age',false);
19534                 }]);
19535             </file>
19536         </example>
19537          */
19538         orderByFilter.$inject = ['$parse'];
19539         function orderByFilter($parse) {
19540           return function(array, sortPredicate, reverseOrder) {
19541
19542             if (!(isArrayLike(array))) return array;
19543
19544             if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
19545             if (sortPredicate.length === 0) { sortPredicate = ['+']; }
19546
19547             var predicates = processPredicates(sortPredicate, reverseOrder);
19548             // Add a predicate at the end that evaluates to the element index. This makes the
19549             // sort stable as it works as a tie-breaker when all the input predicates cannot
19550             // distinguish between two elements.
19551             predicates.push({ get: function() { return {}; }, descending: reverseOrder ? -1 : 1});
19552
19553             // The next three lines are a version of a Swartzian Transform idiom from Perl
19554             // (sometimes called the Decorate-Sort-Undecorate idiom)
19555             // See https://en.wikipedia.org/wiki/Schwartzian_transform
19556             var compareValues = Array.prototype.map.call(array, getComparisonObject);
19557             compareValues.sort(doComparison);
19558             array = compareValues.map(function(item) { return item.value; });
19559
19560             return array;
19561
19562             function getComparisonObject(value, index) {
19563               return {
19564                 value: value,
19565                 predicateValues: predicates.map(function(predicate) {
19566                   return getPredicateValue(predicate.get(value), index);
19567                 })
19568               };
19569             }
19570
19571             function doComparison(v1, v2) {
19572               var result = 0;
19573               for (var index=0, length = predicates.length; index < length; ++index) {
19574                 result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending;
19575                 if (result) break;
19576               }
19577               return result;
19578             }
19579           };
19580
19581           function processPredicates(sortPredicate, reverseOrder) {
19582             reverseOrder = reverseOrder ? -1 : 1;
19583             return sortPredicate.map(function(predicate) {
19584               var descending = 1, get = identity;
19585
19586               if (isFunction(predicate)) {
19587                 get = predicate;
19588               } else if (isString(predicate)) {
19589                 if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
19590                   descending = predicate.charAt(0) == '-' ? -1 : 1;
19591                   predicate = predicate.substring(1);
19592                 }
19593                 if (predicate !== '') {
19594                   get = $parse(predicate);
19595                   if (get.constant) {
19596                     var key = get();
19597                     get = function(value) { return value[key]; };
19598                   }
19599                 }
19600               }
19601               return { get: get, descending: descending * reverseOrder };
19602             });
19603           }
19604
19605           function isPrimitive(value) {
19606             switch (typeof value) {
19607               case 'number': /* falls through */
19608               case 'boolean': /* falls through */
19609               case 'string':
19610                 return true;
19611               default:
19612                 return false;
19613             }
19614           }
19615
19616           function objectValue(value, index) {
19617             // If `valueOf` is a valid function use that
19618             if (typeof value.valueOf === 'function') {
19619               value = value.valueOf();
19620               if (isPrimitive(value)) return value;
19621             }
19622             // If `toString` is a valid function and not the one from `Object.prototype` use that
19623             if (hasCustomToString(value)) {
19624               value = value.toString();
19625               if (isPrimitive(value)) return value;
19626             }
19627             // We have a basic object so we use the position of the object in the collection
19628             return index;
19629           }
19630
19631           function getPredicateValue(value, index) {
19632             var type = typeof value;
19633             if (value === null) {
19634               type = 'string';
19635               value = 'null';
19636             } else if (type === 'string') {
19637               value = value.toLowerCase();
19638             } else if (type === 'object') {
19639               value = objectValue(value, index);
19640             }
19641             return { value: value, type: type };
19642           }
19643
19644           function compare(v1, v2) {
19645             var result = 0;
19646             if (v1.type === v2.type) {
19647               if (v1.value !== v2.value) {
19648                 result = v1.value < v2.value ? -1 : 1;
19649               }
19650             } else {
19651               result = v1.type < v2.type ? -1 : 1;
19652             }
19653             return result;
19654           }
19655         }
19656
19657         function ngDirective(directive) {
19658           if (isFunction(directive)) {
19659             directive = {
19660               link: directive
19661             };
19662           }
19663           directive.restrict = directive.restrict || 'AC';
19664           return valueFn(directive);
19665         }
19666
19667         /**
19668          * @ngdoc directive
19669          * @name a
19670          * @restrict E
19671          *
19672          * @description
19673          * Modifies the default behavior of the html A tag so that the default action is prevented when
19674          * the href attribute is empty.
19675          *
19676          * This change permits the easy creation of action links with the `ngClick` directive
19677          * without changing the location or causing page reloads, e.g.:
19678          * `<a href="" ng-click="list.addItem()">Add Item</a>`
19679          */
19680         var htmlAnchorDirective = valueFn({
19681           restrict: 'E',
19682           compile: function(element, attr) {
19683             if (!attr.href && !attr.xlinkHref) {
19684               return function(scope, element) {
19685                 // If the linked element is not an anchor tag anymore, do nothing
19686                 if (element[0].nodeName.toLowerCase() !== 'a') return;
19687
19688                 // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
19689                 var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
19690                            'xlink:href' : 'href';
19691                 element.on('click', function(event) {
19692                   // if we have no href url, then don't navigate anywhere.
19693                   if (!element.attr(href)) {
19694                     event.preventDefault();
19695                   }
19696                 });
19697               };
19698             }
19699           }
19700         });
19701
19702         /**
19703          * @ngdoc directive
19704          * @name ngHref
19705          * @restrict A
19706          * @priority 99
19707          *
19708          * @description
19709          * Using Angular markup like `{{hash}}` in an href attribute will
19710          * make the link go to the wrong URL if the user clicks it before
19711          * Angular has a chance to replace the `{{hash}}` markup with its
19712          * value. Until Angular replaces the markup the link will be broken
19713          * and will most likely return a 404 error. The `ngHref` directive
19714          * solves this problem.
19715          *
19716          * The wrong way to write it:
19717          * ```html
19718          * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
19719          * ```
19720          *
19721          * The correct way to write it:
19722          * ```html
19723          * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
19724          * ```
19725          *
19726          * @element A
19727          * @param {template} ngHref any string which can contain `{{}}` markup.
19728          *
19729          * @example
19730          * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
19731          * in links and their different behaviors:
19732             <example>
19733               <file name="index.html">
19734                 <input ng-model="value" /><br />
19735                 <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
19736                 <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
19737                 <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
19738                 <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
19739                 <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
19740                 <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
19741               </file>
19742               <file name="protractor.js" type="protractor">
19743                 it('should execute ng-click but not reload when href without value', function() {
19744                   element(by.id('link-1')).click();
19745                   expect(element(by.model('value')).getAttribute('value')).toEqual('1');
19746                   expect(element(by.id('link-1')).getAttribute('href')).toBe('');
19747                 });
19748
19749                 it('should execute ng-click but not reload when href empty string', function() {
19750                   element(by.id('link-2')).click();
19751                   expect(element(by.model('value')).getAttribute('value')).toEqual('2');
19752                   expect(element(by.id('link-2')).getAttribute('href')).toBe('');
19753                 });
19754
19755                 it('should execute ng-click and change url when ng-href specified', function() {
19756                   expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);
19757
19758                   element(by.id('link-3')).click();
19759
19760                   // At this point, we navigate away from an Angular page, so we need
19761                   // to use browser.driver to get the base webdriver.
19762
19763                   browser.wait(function() {
19764                     return browser.driver.getCurrentUrl().then(function(url) {
19765                       return url.match(/\/123$/);
19766                     });
19767                   }, 5000, 'page should navigate to /123');
19768                 });
19769
19770                 it('should execute ng-click but not reload when href empty string and name specified', function() {
19771                   element(by.id('link-4')).click();
19772                   expect(element(by.model('value')).getAttribute('value')).toEqual('4');
19773                   expect(element(by.id('link-4')).getAttribute('href')).toBe('');
19774                 });
19775
19776                 it('should execute ng-click but not reload when no href but name specified', function() {
19777                   element(by.id('link-5')).click();
19778                   expect(element(by.model('value')).getAttribute('value')).toEqual('5');
19779                   expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
19780                 });
19781
19782                 it('should only change url when only ng-href', function() {
19783                   element(by.model('value')).clear();
19784                   element(by.model('value')).sendKeys('6');
19785                   expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);
19786
19787                   element(by.id('link-6')).click();
19788
19789                   // At this point, we navigate away from an Angular page, so we need
19790                   // to use browser.driver to get the base webdriver.
19791                   browser.wait(function() {
19792                     return browser.driver.getCurrentUrl().then(function(url) {
19793                       return url.match(/\/6$/);
19794                     });
19795                   }, 5000, 'page should navigate to /6');
19796                 });
19797               </file>
19798             </example>
19799          */
19800
19801         /**
19802          * @ngdoc directive
19803          * @name ngSrc
19804          * @restrict A
19805          * @priority 99
19806          *
19807          * @description
19808          * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
19809          * work right: The browser will fetch from the URL with the literal
19810          * text `{{hash}}` until Angular replaces the expression inside
19811          * `{{hash}}`. The `ngSrc` directive solves this problem.
19812          *
19813          * The buggy way to write it:
19814          * ```html
19815          * <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/>
19816          * ```
19817          *
19818          * The correct way to write it:
19819          * ```html
19820          * <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />
19821          * ```
19822          *
19823          * @element IMG
19824          * @param {template} ngSrc any string which can contain `{{}}` markup.
19825          */
19826
19827         /**
19828          * @ngdoc directive
19829          * @name ngSrcset
19830          * @restrict A
19831          * @priority 99
19832          *
19833          * @description
19834          * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
19835          * work right: The browser will fetch from the URL with the literal
19836          * text `{{hash}}` until Angular replaces the expression inside
19837          * `{{hash}}`. The `ngSrcset` directive solves this problem.
19838          *
19839          * The buggy way to write it:
19840          * ```html
19841          * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/>
19842          * ```
19843          *
19844          * The correct way to write it:
19845          * ```html
19846          * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" />
19847          * ```
19848          *
19849          * @element IMG
19850          * @param {template} ngSrcset any string which can contain `{{}}` markup.
19851          */
19852
19853         /**
19854          * @ngdoc directive
19855          * @name ngDisabled
19856          * @restrict A
19857          * @priority 100
19858          *
19859          * @description
19860          *
19861          * This directive sets the `disabled` attribute on the element if the
19862          * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
19863          *
19864          * A special directive is necessary because we cannot use interpolation inside the `disabled`
19865          * attribute.  The following example would make the button enabled on Chrome/Firefox
19866          * but not on older IEs:
19867          *
19868          * ```html
19869          * <!-- See below for an example of ng-disabled being used correctly -->
19870          * <div ng-init="isDisabled = false">
19871          *  <button disabled="{{isDisabled}}">Disabled</button>
19872          * </div>
19873          * ```
19874          *
19875          * This is because the HTML specification does not require browsers to preserve the values of
19876          * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
19877          * If we put an Angular interpolation expression into such an attribute then the
19878          * binding information would be lost when the browser removes the attribute.
19879          *
19880          * @example
19881             <example>
19882               <file name="index.html">
19883                 <label>Click me to toggle: <input type="checkbox" ng-model="checked"></label><br/>
19884                 <button ng-model="button" ng-disabled="checked">Button</button>
19885               </file>
19886               <file name="protractor.js" type="protractor">
19887                 it('should toggle button', function() {
19888                   expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
19889                   element(by.model('checked')).click();
19890                   expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
19891                 });
19892               </file>
19893             </example>
19894          *
19895          * @element INPUT
19896          * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
19897          *     then the `disabled` attribute will be set on the element
19898          */
19899
19900
19901         /**
19902          * @ngdoc directive
19903          * @name ngChecked
19904          * @restrict A
19905          * @priority 100
19906          *
19907          * @description
19908          * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.
19909          *
19910          * Note that this directive should not be used together with {@link ngModel `ngModel`},
19911          * as this can lead to unexpected behavior.
19912          *
19913          * ### Why do we need `ngChecked`?
19914          *
19915          * The HTML specification does not require browsers to preserve the values of boolean attributes
19916          * such as checked. (Their presence means true and their absence means false.)
19917          * If we put an Angular interpolation expression into such an attribute then the
19918          * binding information would be lost when the browser removes the attribute.
19919          * The `ngChecked` directive solves this problem for the `checked` attribute.
19920          * This complementary directive is not removed by the browser and so provides
19921          * a permanent reliable place to store the binding information.
19922          * @example
19923             <example>
19924               <file name="index.html">
19925                 <label>Check me to check both: <input type="checkbox" ng-model="master"></label><br/>
19926                 <input id="checkSlave" type="checkbox" ng-checked="master" aria-label="Slave input">
19927               </file>
19928               <file name="protractor.js" type="protractor">
19929                 it('should check both checkBoxes', function() {
19930                   expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
19931                   element(by.model('master')).click();
19932                   expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
19933                 });
19934               </file>
19935             </example>
19936          *
19937          * @element INPUT
19938          * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
19939          *     then the `checked` attribute will be set on the element
19940          */
19941
19942
19943         /**
19944          * @ngdoc directive
19945          * @name ngReadonly
19946          * @restrict A
19947          * @priority 100
19948          *
19949          * @description
19950          * The HTML specification does not require browsers to preserve the values of boolean attributes
19951          * such as readonly. (Their presence means true and their absence means false.)
19952          * If we put an Angular interpolation expression into such an attribute then the
19953          * binding information would be lost when the browser removes the attribute.
19954          * The `ngReadonly` directive solves this problem for the `readonly` attribute.
19955          * This complementary directive is not removed by the browser and so provides
19956          * a permanent reliable place to store the binding information.
19957          * @example
19958             <example>
19959               <file name="index.html">
19960                 <label>Check me to make text readonly: <input type="checkbox" ng-model="checked"></label><br/>
19961                 <input type="text" ng-readonly="checked" value="I'm Angular" aria-label="Readonly field" />
19962               </file>
19963               <file name="protractor.js" type="protractor">
19964                 it('should toggle readonly attr', function() {
19965                   expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
19966                   element(by.model('checked')).click();
19967                   expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
19968                 });
19969               </file>
19970             </example>
19971          *
19972          * @element INPUT
19973          * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
19974          *     then special attribute "readonly" will be set on the element
19975          */
19976
19977
19978         /**
19979          * @ngdoc directive
19980          * @name ngSelected
19981          * @restrict A
19982          * @priority 100
19983          *
19984          * @description
19985          * The HTML specification does not require browsers to preserve the values of boolean attributes
19986          * such as selected. (Their presence means true and their absence means false.)
19987          * If we put an Angular interpolation expression into such an attribute then the
19988          * binding information would be lost when the browser removes the attribute.
19989          * The `ngSelected` directive solves this problem for the `selected` attribute.
19990          * This complementary directive is not removed by the browser and so provides
19991          * a permanent reliable place to store the binding information.
19992          *
19993          * @example
19994             <example>
19995               <file name="index.html">
19996                 <label>Check me to select: <input type="checkbox" ng-model="selected"></label><br/>
19997                 <select aria-label="ngSelected demo">
19998                   <option>Hello!</option>
19999                   <option id="greet" ng-selected="selected">Greetings!</option>
20000                 </select>
20001               </file>
20002               <file name="protractor.js" type="protractor">
20003                 it('should select Greetings!', function() {
20004                   expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
20005                   element(by.model('selected')).click();
20006                   expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
20007                 });
20008               </file>
20009             </example>
20010          *
20011          * @element OPTION
20012          * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
20013          *     then special attribute "selected" will be set on the element
20014          */
20015
20016         /**
20017          * @ngdoc directive
20018          * @name ngOpen
20019          * @restrict A
20020          * @priority 100
20021          *
20022          * @description
20023          * The HTML specification does not require browsers to preserve the values of boolean attributes
20024          * such as open. (Their presence means true and their absence means false.)
20025          * If we put an Angular interpolation expression into such an attribute then the
20026          * binding information would be lost when the browser removes the attribute.
20027          * The `ngOpen` directive solves this problem for the `open` attribute.
20028          * This complementary directive is not removed by the browser and so provides
20029          * a permanent reliable place to store the binding information.
20030          * @example
20031              <example>
20032                <file name="index.html">
20033                  <label>Check me check multiple: <input type="checkbox" ng-model="open"></label><br/>
20034                  <details id="details" ng-open="open">
20035                     <summary>Show/Hide me</summary>
20036                  </details>
20037                </file>
20038                <file name="protractor.js" type="protractor">
20039                  it('should toggle open', function() {
20040                    expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
20041                    element(by.model('open')).click();
20042                    expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
20043                  });
20044                </file>
20045              </example>
20046          *
20047          * @element DETAILS
20048          * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
20049          *     then special attribute "open" will be set on the element
20050          */
20051
20052         var ngAttributeAliasDirectives = {};
20053
20054         // boolean attrs are evaluated
20055         forEach(BOOLEAN_ATTR, function(propName, attrName) {
20056           // binding to multiple is not supported
20057           if (propName == "multiple") return;
20058
20059           function defaultLinkFn(scope, element, attr) {
20060             scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
20061               attr.$set(attrName, !!value);
20062             });
20063           }
20064
20065           var normalized = directiveNormalize('ng-' + attrName);
20066           var linkFn = defaultLinkFn;
20067
20068           if (propName === 'checked') {
20069             linkFn = function(scope, element, attr) {
20070               // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
20071               if (attr.ngModel !== attr[normalized]) {
20072                 defaultLinkFn(scope, element, attr);
20073               }
20074             };
20075           }
20076
20077           ngAttributeAliasDirectives[normalized] = function() {
20078             return {
20079               restrict: 'A',
20080               priority: 100,
20081               link: linkFn
20082             };
20083           };
20084         });
20085
20086         // aliased input attrs are evaluated
20087         forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
20088           ngAttributeAliasDirectives[ngAttr] = function() {
20089             return {
20090               priority: 100,
20091               link: function(scope, element, attr) {
20092                 //special case ngPattern when a literal regular expression value
20093                 //is used as the expression (this way we don't have to watch anything).
20094                 if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
20095                   var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
20096                   if (match) {
20097                     attr.$set("ngPattern", new RegExp(match[1], match[2]));
20098                     return;
20099                   }
20100                 }
20101
20102                 scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
20103                   attr.$set(ngAttr, value);
20104                 });
20105               }
20106             };
20107           };
20108         });
20109
20110         // ng-src, ng-srcset, ng-href are interpolated
20111         forEach(['src', 'srcset', 'href'], function(attrName) {
20112           var normalized = directiveNormalize('ng-' + attrName);
20113           ngAttributeAliasDirectives[normalized] = function() {
20114             return {
20115               priority: 99, // it needs to run after the attributes are interpolated
20116               link: function(scope, element, attr) {
20117                 var propName = attrName,
20118                     name = attrName;
20119
20120                 if (attrName === 'href' &&
20121                     toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
20122                   name = 'xlinkHref';
20123                   attr.$attr[name] = 'xlink:href';
20124                   propName = null;
20125                 }
20126
20127                 attr.$observe(normalized, function(value) {
20128                   if (!value) {
20129                     if (attrName === 'href') {
20130                       attr.$set(name, null);
20131                     }
20132                     return;
20133                   }
20134
20135                   attr.$set(name, value);
20136
20137                   // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
20138                   // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
20139                   // to set the property as well to achieve the desired effect.
20140                   // we use attr[attrName] value since $set can sanitize the url.
20141                   if (msie && propName) element.prop(propName, attr[name]);
20142                 });
20143               }
20144             };
20145           };
20146         });
20147
20148         /* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true
20149          */
20150         var nullFormCtrl = {
20151           $addControl: noop,
20152           $$renameControl: nullFormRenameControl,
20153           $removeControl: noop,
20154           $setValidity: noop,
20155           $setDirty: noop,
20156           $setPristine: noop,
20157           $setSubmitted: noop
20158         },
20159         SUBMITTED_CLASS = 'ng-submitted';
20160
20161         function nullFormRenameControl(control, name) {
20162           control.$name = name;
20163         }
20164
20165         /**
20166          * @ngdoc type
20167          * @name form.FormController
20168          *
20169          * @property {boolean} $pristine True if user has not interacted with the form yet.
20170          * @property {boolean} $dirty True if user has already interacted with the form.
20171          * @property {boolean} $valid True if all of the containing forms and controls are valid.
20172          * @property {boolean} $invalid True if at least one containing control or form is invalid.
20173          * @property {boolean} $pending True if at least one containing control or form is pending.
20174          * @property {boolean} $submitted True if user has submitted the form even if its invalid.
20175          *
20176          * @property {Object} $error Is an object hash, containing references to controls or
20177          *  forms with failing validators, where:
20178          *
20179          *  - keys are validation tokens (error names),
20180          *  - values are arrays of controls or forms that have a failing validator for given error name.
20181          *
20182          *  Built-in validation tokens:
20183          *
20184          *  - `email`
20185          *  - `max`
20186          *  - `maxlength`
20187          *  - `min`
20188          *  - `minlength`
20189          *  - `number`
20190          *  - `pattern`
20191          *  - `required`
20192          *  - `url`
20193          *  - `date`
20194          *  - `datetimelocal`
20195          *  - `time`
20196          *  - `week`
20197          *  - `month`
20198          *
20199          * @description
20200          * `FormController` keeps track of all its controls and nested forms as well as the state of them,
20201          * such as being valid/invalid or dirty/pristine.
20202          *
20203          * Each {@link ng.directive:form form} directive creates an instance
20204          * of `FormController`.
20205          *
20206          */
20207         //asks for $scope to fool the BC controller module
20208         FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];
20209         function FormController(element, attrs, $scope, $animate, $interpolate) {
20210           var form = this,
20211               controls = [];
20212
20213           // init state
20214           form.$error = {};
20215           form.$$success = {};
20216           form.$pending = undefined;
20217           form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);
20218           form.$dirty = false;
20219           form.$pristine = true;
20220           form.$valid = true;
20221           form.$invalid = false;
20222           form.$submitted = false;
20223           form.$$parentForm = nullFormCtrl;
20224
20225           /**
20226            * @ngdoc method
20227            * @name form.FormController#$rollbackViewValue
20228            *
20229            * @description
20230            * Rollback all form controls pending updates to the `$modelValue`.
20231            *
20232            * Updates may be pending by a debounced event or because the input is waiting for a some future
20233            * event defined in `ng-model-options`. This method is typically needed by the reset button of
20234            * a form that uses `ng-model-options` to pend updates.
20235            */
20236           form.$rollbackViewValue = function() {
20237             forEach(controls, function(control) {
20238               control.$rollbackViewValue();
20239             });
20240           };
20241
20242           /**
20243            * @ngdoc method
20244            * @name form.FormController#$commitViewValue
20245            *
20246            * @description
20247            * Commit all form controls pending updates to the `$modelValue`.
20248            *
20249            * Updates may be pending by a debounced event or because the input is waiting for a some future
20250            * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`
20251            * usually handles calling this in response to input events.
20252            */
20253           form.$commitViewValue = function() {
20254             forEach(controls, function(control) {
20255               control.$commitViewValue();
20256             });
20257           };
20258
20259           /**
20260            * @ngdoc method
20261            * @name form.FormController#$addControl
20262            * @param {object} control control object, either a {@link form.FormController} or an
20263            * {@link ngModel.NgModelController}
20264            *
20265            * @description
20266            * Register a control with the form. Input elements using ngModelController do this automatically
20267            * when they are linked.
20268            *
20269            * Note that the current state of the control will not be reflected on the new parent form. This
20270            * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`
20271            * state.
20272            *
20273            * However, if the method is used programmatically, for example by adding dynamically created controls,
20274            * or controls that have been previously removed without destroying their corresponding DOM element,
20275            * it's the developers responsiblity to make sure the current state propagates to the parent form.
20276            *
20277            * For example, if an input control is added that is already `$dirty` and has `$error` properties,
20278            * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
20279            */
20280           form.$addControl = function(control) {
20281             // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
20282             // and not added to the scope.  Now we throw an error.
20283             assertNotHasOwnProperty(control.$name, 'input');
20284             controls.push(control);
20285
20286             if (control.$name) {
20287               form[control.$name] = control;
20288             }
20289
20290             control.$$parentForm = form;
20291           };
20292
20293           // Private API: rename a form control
20294           form.$$renameControl = function(control, newName) {
20295             var oldName = control.$name;
20296
20297             if (form[oldName] === control) {
20298               delete form[oldName];
20299             }
20300             form[newName] = control;
20301             control.$name = newName;
20302           };
20303
20304           /**
20305            * @ngdoc method
20306            * @name form.FormController#$removeControl
20307            * @param {object} control control object, either a {@link form.FormController} or an
20308            * {@link ngModel.NgModelController}
20309            *
20310            * @description
20311            * Deregister a control from the form.
20312            *
20313            * Input elements using ngModelController do this automatically when they are destroyed.
20314            *
20315            * Note that only the removed control's validation state (`$errors`etc.) will be removed from the
20316            * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be
20317            * different from case to case. For example, removing the only `$dirty` control from a form may or
20318            * may not mean that the form is still `$dirty`.
20319            */
20320           form.$removeControl = function(control) {
20321             if (control.$name && form[control.$name] === control) {
20322               delete form[control.$name];
20323             }
20324             forEach(form.$pending, function(value, name) {
20325               form.$setValidity(name, null, control);
20326             });
20327             forEach(form.$error, function(value, name) {
20328               form.$setValidity(name, null, control);
20329             });
20330             forEach(form.$$success, function(value, name) {
20331               form.$setValidity(name, null, control);
20332             });
20333
20334             arrayRemove(controls, control);
20335             control.$$parentForm = nullFormCtrl;
20336           };
20337
20338
20339           /**
20340            * @ngdoc method
20341            * @name form.FormController#$setValidity
20342            *
20343            * @description
20344            * Sets the validity of a form control.
20345            *
20346            * This method will also propagate to parent forms.
20347            */
20348           addSetValidityMethod({
20349             ctrl: this,
20350             $element: element,
20351             set: function(object, property, controller) {
20352               var list = object[property];
20353               if (!list) {
20354                 object[property] = [controller];
20355               } else {
20356                 var index = list.indexOf(controller);
20357                 if (index === -1) {
20358                   list.push(controller);
20359                 }
20360               }
20361             },
20362             unset: function(object, property, controller) {
20363               var list = object[property];
20364               if (!list) {
20365                 return;
20366               }
20367               arrayRemove(list, controller);
20368               if (list.length === 0) {
20369                 delete object[property];
20370               }
20371             },
20372             $animate: $animate
20373           });
20374
20375           /**
20376            * @ngdoc method
20377            * @name form.FormController#$setDirty
20378            *
20379            * @description
20380            * Sets the form to a dirty state.
20381            *
20382            * This method can be called to add the 'ng-dirty' class and set the form to a dirty
20383            * state (ng-dirty class). This method will also propagate to parent forms.
20384            */
20385           form.$setDirty = function() {
20386             $animate.removeClass(element, PRISTINE_CLASS);
20387             $animate.addClass(element, DIRTY_CLASS);
20388             form.$dirty = true;
20389             form.$pristine = false;
20390             form.$$parentForm.$setDirty();
20391           };
20392
20393           /**
20394            * @ngdoc method
20395            * @name form.FormController#$setPristine
20396            *
20397            * @description
20398            * Sets the form to its pristine state.
20399            *
20400            * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
20401            * state (ng-pristine class). This method will also propagate to all the controls contained
20402            * in this form.
20403            *
20404            * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
20405            * saving or resetting it.
20406            */
20407           form.$setPristine = function() {
20408             $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
20409             form.$dirty = false;
20410             form.$pristine = true;
20411             form.$submitted = false;
20412             forEach(controls, function(control) {
20413               control.$setPristine();
20414             });
20415           };
20416
20417           /**
20418            * @ngdoc method
20419            * @name form.FormController#$setUntouched
20420            *
20421            * @description
20422            * Sets the form to its untouched state.
20423            *
20424            * This method can be called to remove the 'ng-touched' class and set the form controls to their
20425            * untouched state (ng-untouched class).
20426            *
20427            * Setting a form controls back to their untouched state is often useful when setting the form
20428            * back to its pristine state.
20429            */
20430           form.$setUntouched = function() {
20431             forEach(controls, function(control) {
20432               control.$setUntouched();
20433             });
20434           };
20435
20436           /**
20437            * @ngdoc method
20438            * @name form.FormController#$setSubmitted
20439            *
20440            * @description
20441            * Sets the form to its submitted state.
20442            */
20443           form.$setSubmitted = function() {
20444             $animate.addClass(element, SUBMITTED_CLASS);
20445             form.$submitted = true;
20446             form.$$parentForm.$setSubmitted();
20447           };
20448         }
20449
20450         /**
20451          * @ngdoc directive
20452          * @name ngForm
20453          * @restrict EAC
20454          *
20455          * @description
20456          * Nestable alias of {@link ng.directive:form `form`} directive. HTML
20457          * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
20458          * sub-group of controls needs to be determined.
20459          *
20460          * Note: the purpose of `ngForm` is to group controls,
20461          * but not to be a replacement for the `<form>` tag with all of its capabilities
20462          * (e.g. posting to the server, ...).
20463          *
20464          * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
20465          *                       related scope, under this name.
20466          *
20467          */
20468
20469          /**
20470          * @ngdoc directive
20471          * @name form
20472          * @restrict E
20473          *
20474          * @description
20475          * Directive that instantiates
20476          * {@link form.FormController FormController}.
20477          *
20478          * If the `name` attribute is specified, the form controller is published onto the current scope under
20479          * this name.
20480          *
20481          * # Alias: {@link ng.directive:ngForm `ngForm`}
20482          *
20483          * In Angular, forms can be nested. This means that the outer form is valid when all of the child
20484          * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
20485          * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
20486          * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when
20487          * using Angular validation directives in forms that are dynamically generated using the
20488          * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
20489          * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
20490          * `ngForm` directive and nest these in an outer `form` element.
20491          *
20492          *
20493          * # CSS classes
20494          *  - `ng-valid` is set if the form is valid.
20495          *  - `ng-invalid` is set if the form is invalid.
20496          *  - `ng-pending` is set if the form is pending.
20497          *  - `ng-pristine` is set if the form is pristine.
20498          *  - `ng-dirty` is set if the form is dirty.
20499          *  - `ng-submitted` is set if the form was submitted.
20500          *
20501          * Keep in mind that ngAnimate can detect each of these classes when added and removed.
20502          *
20503          *
20504          * # Submitting a form and preventing the default action
20505          *
20506          * Since the role of forms in client-side Angular applications is different than in classical
20507          * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
20508          * page reload that sends the data to the server. Instead some javascript logic should be triggered
20509          * to handle the form submission in an application-specific way.
20510          *
20511          * For this reason, Angular prevents the default action (form submission to the server) unless the
20512          * `<form>` element has an `action` attribute specified.
20513          *
20514          * You can use one of the following two ways to specify what javascript method should be called when
20515          * a form is submitted:
20516          *
20517          * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
20518          * - {@link ng.directive:ngClick ngClick} directive on the first
20519           *  button or input field of type submit (input[type=submit])
20520          *
20521          * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
20522          * or {@link ng.directive:ngClick ngClick} directives.
20523          * This is because of the following form submission rules in the HTML specification:
20524          *
20525          * - If a form has only one input field then hitting enter in this field triggers form submit
20526          * (`ngSubmit`)
20527          * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
20528          * doesn't trigger submit
20529          * - if a form has one or more input fields and one or more buttons or input[type=submit] then
20530          * hitting enter in any of the input fields will trigger the click handler on the *first* button or
20531          * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
20532          *
20533          * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is
20534          * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
20535          * to have access to the updated model.
20536          *
20537          * ## Animation Hooks
20538          *
20539          * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
20540          * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
20541          * other validations that are performed within the form. Animations in ngForm are similar to how
20542          * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
20543          * as JS animations.
20544          *
20545          * The following example shows a simple way to utilize CSS transitions to style a form element
20546          * that has been rendered as invalid after it has been validated:
20547          *
20548          * <pre>
20549          * //be sure to include ngAnimate as a module to hook into more
20550          * //advanced animations
20551          * .my-form {
20552          *   transition:0.5s linear all;
20553          *   background: white;
20554          * }
20555          * .my-form.ng-invalid {
20556          *   background: red;
20557          *   color:white;
20558          * }
20559          * </pre>
20560          *
20561          * @example
20562             <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
20563               <file name="index.html">
20564                <script>
20565                  angular.module('formExample', [])
20566                    .controller('FormController', ['$scope', function($scope) {
20567                      $scope.userType = 'guest';
20568                    }]);
20569                </script>
20570                <style>
20571                 .my-form {
20572                   transition:all linear 0.5s;
20573                   background: transparent;
20574                 }
20575                 .my-form.ng-invalid {
20576                   background: red;
20577                 }
20578                </style>
20579                <form name="myForm" ng-controller="FormController" class="my-form">
20580                  userType: <input name="input" ng-model="userType" required>
20581                  <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
20582                  <code>userType = {{userType}}</code><br>
20583                  <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
20584                  <code>myForm.input.$error = {{myForm.input.$error}}</code><br>
20585                  <code>myForm.$valid = {{myForm.$valid}}</code><br>
20586                  <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
20587                 </form>
20588               </file>
20589               <file name="protractor.js" type="protractor">
20590                 it('should initialize to model', function() {
20591                   var userType = element(by.binding('userType'));
20592                   var valid = element(by.binding('myForm.input.$valid'));
20593
20594                   expect(userType.getText()).toContain('guest');
20595                   expect(valid.getText()).toContain('true');
20596                 });
20597
20598                 it('should be invalid if empty', function() {
20599                   var userType = element(by.binding('userType'));
20600                   var valid = element(by.binding('myForm.input.$valid'));
20601                   var userInput = element(by.model('userType'));
20602
20603                   userInput.clear();
20604                   userInput.sendKeys('');
20605
20606                   expect(userType.getText()).toEqual('userType =');
20607                   expect(valid.getText()).toContain('false');
20608                 });
20609               </file>
20610             </example>
20611          *
20612          * @param {string=} name Name of the form. If specified, the form controller will be published into
20613          *                       related scope, under this name.
20614          */
20615         var formDirectiveFactory = function(isNgForm) {
20616           return ['$timeout', '$parse', function($timeout, $parse) {
20617             var formDirective = {
20618               name: 'form',
20619               restrict: isNgForm ? 'EAC' : 'E',
20620               require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form
20621               controller: FormController,
20622               compile: function ngFormCompile(formElement, attr) {
20623                 // Setup initial state of the control
20624                 formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
20625
20626                 var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
20627
20628                 return {
20629                   pre: function ngFormPreLink(scope, formElement, attr, ctrls) {
20630                     var controller = ctrls[0];
20631
20632                     // if `action` attr is not present on the form, prevent the default action (submission)
20633                     if (!('action' in attr)) {
20634                       // we can't use jq events because if a form is destroyed during submission the default
20635                       // action is not prevented. see #1238
20636                       //
20637                       // IE 9 is not affected because it doesn't fire a submit event and try to do a full
20638                       // page reload if the form was destroyed by submission of the form via a click handler
20639                       // on a button in the form. Looks like an IE9 specific bug.
20640                       var handleFormSubmission = function(event) {
20641                         scope.$apply(function() {
20642                           controller.$commitViewValue();
20643                           controller.$setSubmitted();
20644                         });
20645
20646                         event.preventDefault();
20647                       };
20648
20649                       addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
20650
20651                       // unregister the preventDefault listener so that we don't not leak memory but in a
20652                       // way that will achieve the prevention of the default action.
20653                       formElement.on('$destroy', function() {
20654                         $timeout(function() {
20655                           removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);
20656                         }, 0, false);
20657                       });
20658                     }
20659
20660                     var parentFormCtrl = ctrls[1] || controller.$$parentForm;
20661                     parentFormCtrl.$addControl(controller);
20662
20663                     var setter = nameAttr ? getSetter(controller.$name) : noop;
20664
20665                     if (nameAttr) {
20666                       setter(scope, controller);
20667                       attr.$observe(nameAttr, function(newValue) {
20668                         if (controller.$name === newValue) return;
20669                         setter(scope, undefined);
20670                         controller.$$parentForm.$$renameControl(controller, newValue);
20671                         setter = getSetter(controller.$name);
20672                         setter(scope, controller);
20673                       });
20674                     }
20675                     formElement.on('$destroy', function() {
20676                       controller.$$parentForm.$removeControl(controller);
20677                       setter(scope, undefined);
20678                       extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
20679                     });
20680                   }
20681                 };
20682               }
20683             };
20684
20685             return formDirective;
20686
20687             function getSetter(expression) {
20688               if (expression === '') {
20689                 //create an assignable expression, so forms with an empty name can be renamed later
20690                 return $parse('this[""]').assign;
20691               }
20692               return $parse(expression).assign || noop;
20693             }
20694           }];
20695         };
20696
20697         var formDirective = formDirectiveFactory();
20698         var ngFormDirective = formDirectiveFactory(true);
20699
20700         /* global VALID_CLASS: false,
20701           INVALID_CLASS: false,
20702           PRISTINE_CLASS: false,
20703           DIRTY_CLASS: false,
20704           UNTOUCHED_CLASS: false,
20705           TOUCHED_CLASS: false,
20706           ngModelMinErr: false,
20707         */
20708
20709         // Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
20710         var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
20711         // See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
20712         var URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/;
20713         var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
20714         var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
20715         var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
20716         var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
20717         var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
20718         var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
20719         var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
20720
20721         var inputType = {
20722
20723           /**
20724            * @ngdoc input
20725            * @name input[text]
20726            *
20727            * @description
20728            * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
20729            *
20730            *
20731            * @param {string} ngModel Assignable angular expression to data-bind to.
20732            * @param {string=} name Property name of the form under which the control is published.
20733            * @param {string=} required Adds `required` validation error key if the value is not entered.
20734            * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20735            *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20736            *    `required` when you want to data-bind to the `required` attribute.
20737            * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20738            *    minlength.
20739            * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
20740            *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
20741            *    any length.
20742            * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
20743            *    that contains the regular expression body that will be converted to a regular expression
20744            *    as in the ngPattern directive.
20745            * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
20746            *    a RegExp found by evaluating the Angular expression given in the attribute value.
20747            *    If the expression evaluates to a RegExp object, then this is used directly.
20748            *    If the expression evaluates to a string, then it will be converted to a RegExp
20749            *    after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
20750            *    `new RegExp('^abc$')`.<br />
20751            *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
20752            *    start at the index of the last search's match, thus not taking the whole input value into
20753            *    account.
20754            * @param {string=} ngChange Angular expression to be executed when input changes due to user
20755            *    interaction with the input element.
20756            * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
20757            *    This parameter is ignored for input[type=password] controls, which will never trim the
20758            *    input.
20759            *
20760            * @example
20761               <example name="text-input-directive" module="textInputExample">
20762                 <file name="index.html">
20763                  <script>
20764                    angular.module('textInputExample', [])
20765                      .controller('ExampleController', ['$scope', function($scope) {
20766                        $scope.example = {
20767                          text: 'guest',
20768                          word: /^\s*\w*\s*$/
20769                        };
20770                      }]);
20771                  </script>
20772                  <form name="myForm" ng-controller="ExampleController">
20773                    <label>Single word:
20774                      <input type="text" name="input" ng-model="example.text"
20775                             ng-pattern="example.word" required ng-trim="false">
20776                    </label>
20777                    <div role="alert">
20778                      <span class="error" ng-show="myForm.input.$error.required">
20779                        Required!</span>
20780                      <span class="error" ng-show="myForm.input.$error.pattern">
20781                        Single word only!</span>
20782                    </div>
20783                    <tt>text = {{example.text}}</tt><br/>
20784                    <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20785                    <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20786                    <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20787                    <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20788                   </form>
20789                 </file>
20790                 <file name="protractor.js" type="protractor">
20791                   var text = element(by.binding('example.text'));
20792                   var valid = element(by.binding('myForm.input.$valid'));
20793                   var input = element(by.model('example.text'));
20794
20795                   it('should initialize to model', function() {
20796                     expect(text.getText()).toContain('guest');
20797                     expect(valid.getText()).toContain('true');
20798                   });
20799
20800                   it('should be invalid if empty', function() {
20801                     input.clear();
20802                     input.sendKeys('');
20803
20804                     expect(text.getText()).toEqual('text =');
20805                     expect(valid.getText()).toContain('false');
20806                   });
20807
20808                   it('should be invalid if multi word', function() {
20809                     input.clear();
20810                     input.sendKeys('hello world');
20811
20812                     expect(valid.getText()).toContain('false');
20813                   });
20814                 </file>
20815               </example>
20816            */
20817           'text': textInputType,
20818
20819             /**
20820              * @ngdoc input
20821              * @name input[date]
20822              *
20823              * @description
20824              * Input with date validation and transformation. In browsers that do not yet support
20825              * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
20826              * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
20827              * modern browsers do not yet support this input type, it is important to provide cues to users on the
20828              * expected input format via a placeholder or label.
20829              *
20830              * The model must always be a Date object, otherwise Angular will throw an error.
20831              * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
20832              *
20833              * The timezone to be used to read/write the `Date` instance in the model can be defined using
20834              * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
20835              *
20836              * @param {string} ngModel Assignable angular expression to data-bind to.
20837              * @param {string=} name Property name of the form under which the control is published.
20838              * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
20839              *   valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
20840              *   (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5
20841              *   constraint validation.
20842              * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
20843              *   a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
20844              *   (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5
20845              *   constraint validation.
20846              * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string
20847              *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
20848              * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string
20849              *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
20850              * @param {string=} required Sets `required` validation error key if the value is not entered.
20851              * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20852              *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20853              *    `required` when you want to data-bind to the `required` attribute.
20854              * @param {string=} ngChange Angular expression to be executed when input changes due to user
20855              *    interaction with the input element.
20856              *
20857              * @example
20858              <example name="date-input-directive" module="dateInputExample">
20859              <file name="index.html">
20860                <script>
20861                   angular.module('dateInputExample', [])
20862                     .controller('DateController', ['$scope', function($scope) {
20863                       $scope.example = {
20864                         value: new Date(2013, 9, 22)
20865                       };
20866                     }]);
20867                </script>
20868                <form name="myForm" ng-controller="DateController as dateCtrl">
20869                   <label for="exampleInput">Pick a date in 2013:</label>
20870                   <input type="date" id="exampleInput" name="input" ng-model="example.value"
20871                       placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
20872                   <div role="alert">
20873                     <span class="error" ng-show="myForm.input.$error.required">
20874                         Required!</span>
20875                     <span class="error" ng-show="myForm.input.$error.date">
20876                         Not a valid date!</span>
20877                    </div>
20878                    <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
20879                    <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20880                    <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20881                    <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20882                    <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20883                </form>
20884              </file>
20885              <file name="protractor.js" type="protractor">
20886                 var value = element(by.binding('example.value | date: "yyyy-MM-dd"'));
20887                 var valid = element(by.binding('myForm.input.$valid'));
20888                 var input = element(by.model('example.value'));
20889
20890                 // currently protractor/webdriver does not support
20891                 // sending keys to all known HTML5 input controls
20892                 // for various browsers (see https://github.com/angular/protractor/issues/562).
20893                 function setInput(val) {
20894                   // set the value of the element and force validation.
20895                   var scr = "var ipt = document.getElementById('exampleInput'); " +
20896                   "ipt.value = '" + val + "';" +
20897                   "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
20898                   browser.executeScript(scr);
20899                 }
20900
20901                 it('should initialize to model', function() {
20902                   expect(value.getText()).toContain('2013-10-22');
20903                   expect(valid.getText()).toContain('myForm.input.$valid = true');
20904                 });
20905
20906                 it('should be invalid if empty', function() {
20907                   setInput('');
20908                   expect(value.getText()).toEqual('value =');
20909                   expect(valid.getText()).toContain('myForm.input.$valid = false');
20910                 });
20911
20912                 it('should be invalid if over max', function() {
20913                   setInput('2015-01-01');
20914                   expect(value.getText()).toContain('');
20915                   expect(valid.getText()).toContain('myForm.input.$valid = false');
20916                 });
20917              </file>
20918              </example>
20919              */
20920           'date': createDateInputType('date', DATE_REGEXP,
20921                  createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
20922                  'yyyy-MM-dd'),
20923
20924            /**
20925             * @ngdoc input
20926             * @name input[datetime-local]
20927             *
20928             * @description
20929             * Input with datetime validation and transformation. In browsers that do not yet support
20930             * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
20931             * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
20932             *
20933             * The model must always be a Date object, otherwise Angular will throw an error.
20934             * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
20935             *
20936             * The timezone to be used to read/write the `Date` instance in the model can be defined using
20937             * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
20938             *
20939             * @param {string} ngModel Assignable angular expression to data-bind to.
20940             * @param {string=} name Property name of the form under which the control is published.
20941             * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
20942             *   This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
20943             *   inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
20944             *   Note that `min` will also add native HTML5 constraint validation.
20945             * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
20946             *   This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
20947             *   inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
20948             *   Note that `max` will also add native HTML5 constraint validation.
20949             * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string
20950             *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
20951             * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string
20952             *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
20953             * @param {string=} required Sets `required` validation error key if the value is not entered.
20954             * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20955             *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20956             *    `required` when you want to data-bind to the `required` attribute.
20957             * @param {string=} ngChange Angular expression to be executed when input changes due to user
20958             *    interaction with the input element.
20959             *
20960             * @example
20961             <example name="datetimelocal-input-directive" module="dateExample">
20962             <file name="index.html">
20963               <script>
20964                 angular.module('dateExample', [])
20965                   .controller('DateController', ['$scope', function($scope) {
20966                     $scope.example = {
20967                       value: new Date(2010, 11, 28, 14, 57)
20968                     };
20969                   }]);
20970               </script>
20971               <form name="myForm" ng-controller="DateController as dateCtrl">
20972                 <label for="exampleInput">Pick a date between in 2013:</label>
20973                 <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
20974                     placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
20975                 <div role="alert">
20976                   <span class="error" ng-show="myForm.input.$error.required">
20977                       Required!</span>
20978                   <span class="error" ng-show="myForm.input.$error.datetimelocal">
20979                       Not a valid date!</span>
20980                 </div>
20981                 <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
20982                 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20983                 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20984                 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20985                 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20986               </form>
20987             </file>
20988             <file name="protractor.js" type="protractor">
20989               var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"'));
20990               var valid = element(by.binding('myForm.input.$valid'));
20991               var input = element(by.model('example.value'));
20992
20993               // currently protractor/webdriver does not support
20994               // sending keys to all known HTML5 input controls
20995               // for various browsers (https://github.com/angular/protractor/issues/562).
20996               function setInput(val) {
20997                 // set the value of the element and force validation.
20998                 var scr = "var ipt = document.getElementById('exampleInput'); " +
20999                 "ipt.value = '" + val + "';" +
21000                 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
21001                 browser.executeScript(scr);
21002               }
21003
21004               it('should initialize to model', function() {
21005                 expect(value.getText()).toContain('2010-12-28T14:57:00');
21006                 expect(valid.getText()).toContain('myForm.input.$valid = true');
21007               });
21008
21009               it('should be invalid if empty', function() {
21010                 setInput('');
21011                 expect(value.getText()).toEqual('value =');
21012                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21013               });
21014
21015               it('should be invalid if over max', function() {
21016                 setInput('2015-01-01T23:59:00');
21017                 expect(value.getText()).toContain('');
21018                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21019               });
21020             </file>
21021             </example>
21022             */
21023           'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,
21024               createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),
21025               'yyyy-MM-ddTHH:mm:ss.sss'),
21026
21027           /**
21028            * @ngdoc input
21029            * @name input[time]
21030            *
21031            * @description
21032            * Input with time validation and transformation. In browsers that do not yet support
21033            * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
21034            * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
21035            * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
21036            *
21037            * The model must always be a Date object, otherwise Angular will throw an error.
21038            * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
21039            *
21040            * The timezone to be used to read/write the `Date` instance in the model can be defined using
21041            * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
21042            *
21043            * @param {string} ngModel Assignable angular expression to data-bind to.
21044            * @param {string=} name Property name of the form under which the control is published.
21045            * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
21046            *   This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
21047            *   attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add
21048            *   native HTML5 constraint validation.
21049            * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
21050            *   This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
21051            *   attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add
21052            *   native HTML5 constraint validation.
21053            * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the
21054            *   `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
21055            * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the
21056            *   `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
21057            * @param {string=} required Sets `required` validation error key if the value is not entered.
21058            * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21059            *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21060            *    `required` when you want to data-bind to the `required` attribute.
21061            * @param {string=} ngChange Angular expression to be executed when input changes due to user
21062            *    interaction with the input element.
21063            *
21064            * @example
21065            <example name="time-input-directive" module="timeExample">
21066            <file name="index.html">
21067              <script>
21068               angular.module('timeExample', [])
21069                 .controller('DateController', ['$scope', function($scope) {
21070                   $scope.example = {
21071                     value: new Date(1970, 0, 1, 14, 57, 0)
21072                   };
21073                 }]);
21074              </script>
21075              <form name="myForm" ng-controller="DateController as dateCtrl">
21076                 <label for="exampleInput">Pick a between 8am and 5pm:</label>
21077                 <input type="time" id="exampleInput" name="input" ng-model="example.value"
21078                     placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
21079                 <div role="alert">
21080                   <span class="error" ng-show="myForm.input.$error.required">
21081                       Required!</span>
21082                   <span class="error" ng-show="myForm.input.$error.time">
21083                       Not a valid date!</span>
21084                 </div>
21085                 <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
21086                 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21087                 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21088                 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21089                 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21090              </form>
21091            </file>
21092            <file name="protractor.js" type="protractor">
21093               var value = element(by.binding('example.value | date: "HH:mm:ss"'));
21094               var valid = element(by.binding('myForm.input.$valid'));
21095               var input = element(by.model('example.value'));
21096
21097               // currently protractor/webdriver does not support
21098               // sending keys to all known HTML5 input controls
21099               // for various browsers (https://github.com/angular/protractor/issues/562).
21100               function setInput(val) {
21101                 // set the value of the element and force validation.
21102                 var scr = "var ipt = document.getElementById('exampleInput'); " +
21103                 "ipt.value = '" + val + "';" +
21104                 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
21105                 browser.executeScript(scr);
21106               }
21107
21108               it('should initialize to model', function() {
21109                 expect(value.getText()).toContain('14:57:00');
21110                 expect(valid.getText()).toContain('myForm.input.$valid = true');
21111               });
21112
21113               it('should be invalid if empty', function() {
21114                 setInput('');
21115                 expect(value.getText()).toEqual('value =');
21116                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21117               });
21118
21119               it('should be invalid if over max', function() {
21120                 setInput('23:59:00');
21121                 expect(value.getText()).toContain('');
21122                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21123               });
21124            </file>
21125            </example>
21126            */
21127           'time': createDateInputType('time', TIME_REGEXP,
21128               createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),
21129              'HH:mm:ss.sss'),
21130
21131            /**
21132             * @ngdoc input
21133             * @name input[week]
21134             *
21135             * @description
21136             * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
21137             * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
21138             * week format (yyyy-W##), for example: `2013-W02`.
21139             *
21140             * The model must always be a Date object, otherwise Angular will throw an error.
21141             * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
21142             *
21143             * The timezone to be used to read/write the `Date` instance in the model can be defined using
21144             * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
21145             *
21146             * @param {string} ngModel Assignable angular expression to data-bind to.
21147             * @param {string=} name Property name of the form under which the control is published.
21148             * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
21149             *   This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
21150             *   attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add
21151             *   native HTML5 constraint validation.
21152             * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
21153             *   This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
21154             *   attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add
21155             *   native HTML5 constraint validation.
21156             * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
21157             *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
21158             * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
21159             *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
21160             * @param {string=} required Sets `required` validation error key if the value is not entered.
21161             * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21162             *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21163             *    `required` when you want to data-bind to the `required` attribute.
21164             * @param {string=} ngChange Angular expression to be executed when input changes due to user
21165             *    interaction with the input element.
21166             *
21167             * @example
21168             <example name="week-input-directive" module="weekExample">
21169             <file name="index.html">
21170               <script>
21171               angular.module('weekExample', [])
21172                 .controller('DateController', ['$scope', function($scope) {
21173                   $scope.example = {
21174                     value: new Date(2013, 0, 3)
21175                   };
21176                 }]);
21177               </script>
21178               <form name="myForm" ng-controller="DateController as dateCtrl">
21179                 <label>Pick a date between in 2013:
21180                   <input id="exampleInput" type="week" name="input" ng-model="example.value"
21181                          placeholder="YYYY-W##" min="2012-W32"
21182                          max="2013-W52" required />
21183                 </label>
21184                 <div role="alert">
21185                   <span class="error" ng-show="myForm.input.$error.required">
21186                       Required!</span>
21187                   <span class="error" ng-show="myForm.input.$error.week">
21188                       Not a valid date!</span>
21189                 </div>
21190                 <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
21191                 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21192                 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21193                 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21194                 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21195               </form>
21196             </file>
21197             <file name="protractor.js" type="protractor">
21198               var value = element(by.binding('example.value | date: "yyyy-Www"'));
21199               var valid = element(by.binding('myForm.input.$valid'));
21200               var input = element(by.model('example.value'));
21201
21202               // currently protractor/webdriver does not support
21203               // sending keys to all known HTML5 input controls
21204               // for various browsers (https://github.com/angular/protractor/issues/562).
21205               function setInput(val) {
21206                 // set the value of the element and force validation.
21207                 var scr = "var ipt = document.getElementById('exampleInput'); " +
21208                 "ipt.value = '" + val + "';" +
21209                 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
21210                 browser.executeScript(scr);
21211               }
21212
21213               it('should initialize to model', function() {
21214                 expect(value.getText()).toContain('2013-W01');
21215                 expect(valid.getText()).toContain('myForm.input.$valid = true');
21216               });
21217
21218               it('should be invalid if empty', function() {
21219                 setInput('');
21220                 expect(value.getText()).toEqual('value =');
21221                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21222               });
21223
21224               it('should be invalid if over max', function() {
21225                 setInput('2015-W01');
21226                 expect(value.getText()).toContain('');
21227                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21228               });
21229             </file>
21230             </example>
21231             */
21232           'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),
21233
21234           /**
21235            * @ngdoc input
21236            * @name input[month]
21237            *
21238            * @description
21239            * Input with month validation and transformation. In browsers that do not yet support
21240            * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
21241            * month format (yyyy-MM), for example: `2009-01`.
21242            *
21243            * The model must always be a Date object, otherwise Angular will throw an error.
21244            * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
21245            * If the model is not set to the first of the month, the next view to model update will set it
21246            * to the first of the month.
21247            *
21248            * The timezone to be used to read/write the `Date` instance in the model can be defined using
21249            * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
21250            *
21251            * @param {string} ngModel Assignable angular expression to data-bind to.
21252            * @param {string=} name Property name of the form under which the control is published.
21253            * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
21254            *   This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
21255            *   attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add
21256            *   native HTML5 constraint validation.
21257            * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
21258            *   This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
21259            *   attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add
21260            *   native HTML5 constraint validation.
21261            * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
21262            *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
21263            * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
21264            *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
21265
21266            * @param {string=} required Sets `required` validation error key if the value is not entered.
21267            * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21268            *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21269            *    `required` when you want to data-bind to the `required` attribute.
21270            * @param {string=} ngChange Angular expression to be executed when input changes due to user
21271            *    interaction with the input element.
21272            *
21273            * @example
21274            <example name="month-input-directive" module="monthExample">
21275            <file name="index.html">
21276              <script>
21277               angular.module('monthExample', [])
21278                 .controller('DateController', ['$scope', function($scope) {
21279                   $scope.example = {
21280                     value: new Date(2013, 9, 1)
21281                   };
21282                 }]);
21283              </script>
21284              <form name="myForm" ng-controller="DateController as dateCtrl">
21285                <label for="exampleInput">Pick a month in 2013:</label>
21286                <input id="exampleInput" type="month" name="input" ng-model="example.value"
21287                   placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
21288                <div role="alert">
21289                  <span class="error" ng-show="myForm.input.$error.required">
21290                     Required!</span>
21291                  <span class="error" ng-show="myForm.input.$error.month">
21292                     Not a valid month!</span>
21293                </div>
21294                <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
21295                <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21296                <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21297                <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21298                <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21299              </form>
21300            </file>
21301            <file name="protractor.js" type="protractor">
21302               var value = element(by.binding('example.value | date: "yyyy-MM"'));
21303               var valid = element(by.binding('myForm.input.$valid'));
21304               var input = element(by.model('example.value'));
21305
21306               // currently protractor/webdriver does not support
21307               // sending keys to all known HTML5 input controls
21308               // for various browsers (https://github.com/angular/protractor/issues/562).
21309               function setInput(val) {
21310                 // set the value of the element and force validation.
21311                 var scr = "var ipt = document.getElementById('exampleInput'); " +
21312                 "ipt.value = '" + val + "';" +
21313                 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
21314                 browser.executeScript(scr);
21315               }
21316
21317               it('should initialize to model', function() {
21318                 expect(value.getText()).toContain('2013-10');
21319                 expect(valid.getText()).toContain('myForm.input.$valid = true');
21320               });
21321
21322               it('should be invalid if empty', function() {
21323                 setInput('');
21324                 expect(value.getText()).toEqual('value =');
21325                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21326               });
21327
21328               it('should be invalid if over max', function() {
21329                 setInput('2015-01');
21330                 expect(value.getText()).toContain('');
21331                 expect(valid.getText()).toContain('myForm.input.$valid = false');
21332               });
21333            </file>
21334            </example>
21335            */
21336           'month': createDateInputType('month', MONTH_REGEXP,
21337              createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),
21338              'yyyy-MM'),
21339
21340           /**
21341            * @ngdoc input
21342            * @name input[number]
21343            *
21344            * @description
21345            * Text input with number validation and transformation. Sets the `number` validation
21346            * error if not a valid number.
21347            *
21348            * <div class="alert alert-warning">
21349            * The model must always be of type `number` otherwise Angular will throw an error.
21350            * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
21351            * error docs for more information and an example of how to convert your model if necessary.
21352            * </div>
21353            *
21354            * ## Issues with HTML5 constraint validation
21355            *
21356            * In browsers that follow the
21357            * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),
21358            * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.
21359            * If a non-number is entered in the input, the browser will report the value as an empty string,
21360            * which means the view / model values in `ngModel` and subsequently the scope value
21361            * will also be an empty string.
21362            *
21363            *
21364            * @param {string} ngModel Assignable angular expression to data-bind to.
21365            * @param {string=} name Property name of the form under which the control is published.
21366            * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
21367            * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
21368            * @param {string=} required Sets `required` validation error key if the value is not entered.
21369            * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21370            *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21371            *    `required` when you want to data-bind to the `required` attribute.
21372            * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21373            *    minlength.
21374            * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21375            *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
21376            *    any length.
21377            * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
21378            *    that contains the regular expression body that will be converted to a regular expression
21379            *    as in the ngPattern directive.
21380            * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21381            *    a RegExp found by evaluating the Angular expression given in the attribute value.
21382            *    If the expression evaluates to a RegExp object, then this is used directly.
21383            *    If the expression evaluates to a string, then it will be converted to a RegExp
21384            *    after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21385            *    `new RegExp('^abc$')`.<br />
21386            *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21387            *    start at the index of the last search's match, thus not taking the whole input value into
21388            *    account.
21389            * @param {string=} ngChange Angular expression to be executed when input changes due to user
21390            *    interaction with the input element.
21391            *
21392            * @example
21393               <example name="number-input-directive" module="numberExample">
21394                 <file name="index.html">
21395                  <script>
21396                    angular.module('numberExample', [])
21397                      .controller('ExampleController', ['$scope', function($scope) {
21398                        $scope.example = {
21399                          value: 12
21400                        };
21401                      }]);
21402                  </script>
21403                  <form name="myForm" ng-controller="ExampleController">
21404                    <label>Number:
21405                      <input type="number" name="input" ng-model="example.value"
21406                             min="0" max="99" required>
21407                   </label>
21408                    <div role="alert">
21409                      <span class="error" ng-show="myForm.input.$error.required">
21410                        Required!</span>
21411                      <span class="error" ng-show="myForm.input.$error.number">
21412                        Not valid number!</span>
21413                    </div>
21414                    <tt>value = {{example.value}}</tt><br/>
21415                    <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21416                    <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21417                    <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21418                    <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21419                   </form>
21420                 </file>
21421                 <file name="protractor.js" type="protractor">
21422                   var value = element(by.binding('example.value'));
21423                   var valid = element(by.binding('myForm.input.$valid'));
21424                   var input = element(by.model('example.value'));
21425
21426                   it('should initialize to model', function() {
21427                     expect(value.getText()).toContain('12');
21428                     expect(valid.getText()).toContain('true');
21429                   });
21430
21431                   it('should be invalid if empty', function() {
21432                     input.clear();
21433                     input.sendKeys('');
21434                     expect(value.getText()).toEqual('value =');
21435                     expect(valid.getText()).toContain('false');
21436                   });
21437
21438                   it('should be invalid if over max', function() {
21439                     input.clear();
21440                     input.sendKeys('123');
21441                     expect(value.getText()).toEqual('value =');
21442                     expect(valid.getText()).toContain('false');
21443                   });
21444                 </file>
21445               </example>
21446            */
21447           'number': numberInputType,
21448
21449
21450           /**
21451            * @ngdoc input
21452            * @name input[url]
21453            *
21454            * @description
21455            * Text input with URL validation. Sets the `url` validation error key if the content is not a
21456            * valid URL.
21457            *
21458            * <div class="alert alert-warning">
21459            * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
21460            * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
21461            * the built-in validators (see the {@link guide/forms Forms guide})
21462            * </div>
21463            *
21464            * @param {string} ngModel Assignable angular expression to data-bind to.
21465            * @param {string=} name Property name of the form under which the control is published.
21466            * @param {string=} required Sets `required` validation error key if the value is not entered.
21467            * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21468            *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21469            *    `required` when you want to data-bind to the `required` attribute.
21470            * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21471            *    minlength.
21472            * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21473            *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
21474            *    any length.
21475            * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
21476            *    that contains the regular expression body that will be converted to a regular expression
21477            *    as in the ngPattern directive.
21478            * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21479            *    a RegExp found by evaluating the Angular expression given in the attribute value.
21480            *    If the expression evaluates to a RegExp object, then this is used directly.
21481            *    If the expression evaluates to a string, then it will be converted to a RegExp
21482            *    after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21483            *    `new RegExp('^abc$')`.<br />
21484            *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21485            *    start at the index of the last search's match, thus not taking the whole input value into
21486            *    account.
21487            * @param {string=} ngChange Angular expression to be executed when input changes due to user
21488            *    interaction with the input element.
21489            *
21490            * @example
21491               <example name="url-input-directive" module="urlExample">
21492                 <file name="index.html">
21493                  <script>
21494                    angular.module('urlExample', [])
21495                      .controller('ExampleController', ['$scope', function($scope) {
21496                        $scope.url = {
21497                          text: 'http://google.com'
21498                        };
21499                      }]);
21500                  </script>
21501                  <form name="myForm" ng-controller="ExampleController">
21502                    <label>URL:
21503                      <input type="url" name="input" ng-model="url.text" required>
21504                    <label>
21505                    <div role="alert">
21506                      <span class="error" ng-show="myForm.input.$error.required">
21507                        Required!</span>
21508                      <span class="error" ng-show="myForm.input.$error.url">
21509                        Not valid url!</span>
21510                    </div>
21511                    <tt>text = {{url.text}}</tt><br/>
21512                    <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21513                    <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21514                    <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21515                    <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21516                    <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
21517                   </form>
21518                 </file>
21519                 <file name="protractor.js" type="protractor">
21520                   var text = element(by.binding('url.text'));
21521                   var valid = element(by.binding('myForm.input.$valid'));
21522                   var input = element(by.model('url.text'));
21523
21524                   it('should initialize to model', function() {
21525                     expect(text.getText()).toContain('http://google.com');
21526                     expect(valid.getText()).toContain('true');
21527                   });
21528
21529                   it('should be invalid if empty', function() {
21530                     input.clear();
21531                     input.sendKeys('');
21532
21533                     expect(text.getText()).toEqual('text =');
21534                     expect(valid.getText()).toContain('false');
21535                   });
21536
21537                   it('should be invalid if not url', function() {
21538                     input.clear();
21539                     input.sendKeys('box');
21540
21541                     expect(valid.getText()).toContain('false');
21542                   });
21543                 </file>
21544               </example>
21545            */
21546           'url': urlInputType,
21547
21548
21549           /**
21550            * @ngdoc input
21551            * @name input[email]
21552            *
21553            * @description
21554            * Text input with email validation. Sets the `email` validation error key if not a valid email
21555            * address.
21556            *
21557            * <div class="alert alert-warning">
21558            * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
21559            * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
21560            * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
21561            * </div>
21562            *
21563            * @param {string} ngModel Assignable angular expression to data-bind to.
21564            * @param {string=} name Property name of the form under which the control is published.
21565            * @param {string=} required Sets `required` validation error key if the value is not entered.
21566            * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21567            *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21568            *    `required` when you want to data-bind to the `required` attribute.
21569            * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21570            *    minlength.
21571            * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21572            *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
21573            *    any length.
21574            * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
21575            *    that contains the regular expression body that will be converted to a regular expression
21576            *    as in the ngPattern directive.
21577            * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21578            *    a RegExp found by evaluating the Angular expression given in the attribute value.
21579            *    If the expression evaluates to a RegExp object, then this is used directly.
21580            *    If the expression evaluates to a string, then it will be converted to a RegExp
21581            *    after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21582            *    `new RegExp('^abc$')`.<br />
21583            *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21584            *    start at the index of the last search's match, thus not taking the whole input value into
21585            *    account.
21586            * @param {string=} ngChange Angular expression to be executed when input changes due to user
21587            *    interaction with the input element.
21588            *
21589            * @example
21590               <example name="email-input-directive" module="emailExample">
21591                 <file name="index.html">
21592                  <script>
21593                    angular.module('emailExample', [])
21594                      .controller('ExampleController', ['$scope', function($scope) {
21595                        $scope.email = {
21596                          text: 'me@example.com'
21597                        };
21598                      }]);
21599                  </script>
21600                    <form name="myForm" ng-controller="ExampleController">
21601                      <label>Email:
21602                        <input type="email" name="input" ng-model="email.text" required>
21603                      </label>
21604                      <div role="alert">
21605                        <span class="error" ng-show="myForm.input.$error.required">
21606                          Required!</span>
21607                        <span class="error" ng-show="myForm.input.$error.email">
21608                          Not valid email!</span>
21609                      </div>
21610                      <tt>text = {{email.text}}</tt><br/>
21611                      <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21612                      <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21613                      <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21614                      <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21615                      <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
21616                    </form>
21617                  </file>
21618                 <file name="protractor.js" type="protractor">
21619                   var text = element(by.binding('email.text'));
21620                   var valid = element(by.binding('myForm.input.$valid'));
21621                   var input = element(by.model('email.text'));
21622
21623                   it('should initialize to model', function() {
21624                     expect(text.getText()).toContain('me@example.com');
21625                     expect(valid.getText()).toContain('true');
21626                   });
21627
21628                   it('should be invalid if empty', function() {
21629                     input.clear();
21630                     input.sendKeys('');
21631                     expect(text.getText()).toEqual('text =');
21632                     expect(valid.getText()).toContain('false');
21633                   });
21634
21635                   it('should be invalid if not email', function() {
21636                     input.clear();
21637                     input.sendKeys('xxx');
21638
21639                     expect(valid.getText()).toContain('false');
21640                   });
21641                 </file>
21642               </example>
21643            */
21644           'email': emailInputType,
21645
21646
21647           /**
21648            * @ngdoc input
21649            * @name input[radio]
21650            *
21651            * @description
21652            * HTML radio button.
21653            *
21654            * @param {string} ngModel Assignable angular expression to data-bind to.
21655            * @param {string} value The value to which the `ngModel` expression should be set when selected.
21656            *    Note that `value` only supports `string` values, i.e. the scope model needs to be a string,
21657            *    too. Use `ngValue` if you need complex models (`number`, `object`, ...).
21658            * @param {string=} name Property name of the form under which the control is published.
21659            * @param {string=} ngChange Angular expression to be executed when input changes due to user
21660            *    interaction with the input element.
21661            * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio
21662            *    is selected. Should be used instead of the `value` attribute if you need
21663            *    a non-string `ngModel` (`boolean`, `array`, ...).
21664            *
21665            * @example
21666               <example name="radio-input-directive" module="radioExample">
21667                 <file name="index.html">
21668                  <script>
21669                    angular.module('radioExample', [])
21670                      .controller('ExampleController', ['$scope', function($scope) {
21671                        $scope.color = {
21672                          name: 'blue'
21673                        };
21674                        $scope.specialValue = {
21675                          "id": "12345",
21676                          "value": "green"
21677                        };
21678                      }]);
21679                  </script>
21680                  <form name="myForm" ng-controller="ExampleController">
21681                    <label>
21682                      <input type="radio" ng-model="color.name" value="red">
21683                      Red
21684                    </label><br/>
21685                    <label>
21686                      <input type="radio" ng-model="color.name" ng-value="specialValue">
21687                      Green
21688                    </label><br/>
21689                    <label>
21690                      <input type="radio" ng-model="color.name" value="blue">
21691                      Blue
21692                    </label><br/>
21693                    <tt>color = {{color.name | json}}</tt><br/>
21694                   </form>
21695                   Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
21696                 </file>
21697                 <file name="protractor.js" type="protractor">
21698                   it('should change state', function() {
21699                     var color = element(by.binding('color.name'));
21700
21701                     expect(color.getText()).toContain('blue');
21702
21703                     element.all(by.model('color.name')).get(0).click();
21704
21705                     expect(color.getText()).toContain('red');
21706                   });
21707                 </file>
21708               </example>
21709            */
21710           'radio': radioInputType,
21711
21712
21713           /**
21714            * @ngdoc input
21715            * @name input[checkbox]
21716            *
21717            * @description
21718            * HTML checkbox.
21719            *
21720            * @param {string} ngModel Assignable angular expression to data-bind to.
21721            * @param {string=} name Property name of the form under which the control is published.
21722            * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
21723            * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
21724            * @param {string=} ngChange Angular expression to be executed when input changes due to user
21725            *    interaction with the input element.
21726            *
21727            * @example
21728               <example name="checkbox-input-directive" module="checkboxExample">
21729                 <file name="index.html">
21730                  <script>
21731                    angular.module('checkboxExample', [])
21732                      .controller('ExampleController', ['$scope', function($scope) {
21733                        $scope.checkboxModel = {
21734                         value1 : true,
21735                         value2 : 'YES'
21736                       };
21737                      }]);
21738                  </script>
21739                  <form name="myForm" ng-controller="ExampleController">
21740                    <label>Value1:
21741                      <input type="checkbox" ng-model="checkboxModel.value1">
21742                    </label><br/>
21743                    <label>Value2:
21744                      <input type="checkbox" ng-model="checkboxModel.value2"
21745                             ng-true-value="'YES'" ng-false-value="'NO'">
21746                     </label><br/>
21747                    <tt>value1 = {{checkboxModel.value1}}</tt><br/>
21748                    <tt>value2 = {{checkboxModel.value2}}</tt><br/>
21749                   </form>
21750                 </file>
21751                 <file name="protractor.js" type="protractor">
21752                   it('should change state', function() {
21753                     var value1 = element(by.binding('checkboxModel.value1'));
21754                     var value2 = element(by.binding('checkboxModel.value2'));
21755
21756                     expect(value1.getText()).toContain('true');
21757                     expect(value2.getText()).toContain('YES');
21758
21759                     element(by.model('checkboxModel.value1')).click();
21760                     element(by.model('checkboxModel.value2')).click();
21761
21762                     expect(value1.getText()).toContain('false');
21763                     expect(value2.getText()).toContain('NO');
21764                   });
21765                 </file>
21766               </example>
21767            */
21768           'checkbox': checkboxInputType,
21769
21770           'hidden': noop,
21771           'button': noop,
21772           'submit': noop,
21773           'reset': noop,
21774           'file': noop
21775         };
21776
21777         function stringBasedInputType(ctrl) {
21778           ctrl.$formatters.push(function(value) {
21779             return ctrl.$isEmpty(value) ? value : value.toString();
21780           });
21781         }
21782
21783         function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
21784           baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
21785           stringBasedInputType(ctrl);
21786         }
21787
21788         function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
21789           var type = lowercase(element[0].type);
21790
21791           // In composition mode, users are still inputing intermediate text buffer,
21792           // hold the listener until composition is done.
21793           // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
21794           if (!$sniffer.android) {
21795             var composing = false;
21796
21797             element.on('compositionstart', function(data) {
21798               composing = true;
21799             });
21800
21801             element.on('compositionend', function() {
21802               composing = false;
21803               listener();
21804             });
21805           }
21806
21807           var listener = function(ev) {
21808             if (timeout) {
21809               $browser.defer.cancel(timeout);
21810               timeout = null;
21811             }
21812             if (composing) return;
21813             var value = element.val(),
21814                 event = ev && ev.type;
21815
21816             // By default we will trim the value
21817             // If the attribute ng-trim exists we will avoid trimming
21818             // If input type is 'password', the value is never trimmed
21819             if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
21820               value = trim(value);
21821             }
21822
21823             // If a control is suffering from bad input (due to native validators), browsers discard its
21824             // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
21825             // control's value is the same empty value twice in a row.
21826             if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
21827               ctrl.$setViewValue(value, event);
21828             }
21829           };
21830
21831           // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
21832           // input event on backspace, delete or cut
21833           if ($sniffer.hasEvent('input')) {
21834             element.on('input', listener);
21835           } else {
21836             var timeout;
21837
21838             var deferListener = function(ev, input, origValue) {
21839               if (!timeout) {
21840                 timeout = $browser.defer(function() {
21841                   timeout = null;
21842                   if (!input || input.value !== origValue) {
21843                     listener(ev);
21844                   }
21845                 });
21846               }
21847             };
21848
21849             element.on('keydown', function(event) {
21850               var key = event.keyCode;
21851
21852               // ignore
21853               //    command            modifiers                   arrows
21854               if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
21855
21856               deferListener(event, this, this.value);
21857             });
21858
21859             // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
21860             if ($sniffer.hasEvent('paste')) {
21861               element.on('paste cut', deferListener);
21862             }
21863           }
21864
21865           // if user paste into input using mouse on older browser
21866           // or form autocomplete on newer browser, we need "change" event to catch it
21867           element.on('change', listener);
21868
21869           ctrl.$render = function() {
21870             // Workaround for Firefox validation #12102.
21871             var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;
21872             if (element.val() !== value) {
21873               element.val(value);
21874             }
21875           };
21876         }
21877
21878         function weekParser(isoWeek, existingDate) {
21879           if (isDate(isoWeek)) {
21880             return isoWeek;
21881           }
21882
21883           if (isString(isoWeek)) {
21884             WEEK_REGEXP.lastIndex = 0;
21885             var parts = WEEK_REGEXP.exec(isoWeek);
21886             if (parts) {
21887               var year = +parts[1],
21888                   week = +parts[2],
21889                   hours = 0,
21890                   minutes = 0,
21891                   seconds = 0,
21892                   milliseconds = 0,
21893                   firstThurs = getFirstThursdayOfYear(year),
21894                   addDays = (week - 1) * 7;
21895
21896               if (existingDate) {
21897                 hours = existingDate.getHours();
21898                 minutes = existingDate.getMinutes();
21899                 seconds = existingDate.getSeconds();
21900                 milliseconds = existingDate.getMilliseconds();
21901               }
21902
21903               return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);
21904             }
21905           }
21906
21907           return NaN;
21908         }
21909
21910         function createDateParser(regexp, mapping) {
21911           return function(iso, date) {
21912             var parts, map;
21913
21914             if (isDate(iso)) {
21915               return iso;
21916             }
21917
21918             if (isString(iso)) {
21919               // When a date is JSON'ified to wraps itself inside of an extra
21920               // set of double quotes. This makes the date parsing code unable
21921               // to match the date string and parse it as a date.
21922               if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
21923                 iso = iso.substring(1, iso.length - 1);
21924               }
21925               if (ISO_DATE_REGEXP.test(iso)) {
21926                 return new Date(iso);
21927               }
21928               regexp.lastIndex = 0;
21929               parts = regexp.exec(iso);
21930
21931               if (parts) {
21932                 parts.shift();
21933                 if (date) {
21934                   map = {
21935                     yyyy: date.getFullYear(),
21936                     MM: date.getMonth() + 1,
21937                     dd: date.getDate(),
21938                     HH: date.getHours(),
21939                     mm: date.getMinutes(),
21940                     ss: date.getSeconds(),
21941                     sss: date.getMilliseconds() / 1000
21942                   };
21943                 } else {
21944                   map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
21945                 }
21946
21947                 forEach(parts, function(part, index) {
21948                   if (index < mapping.length) {
21949                     map[mapping[index]] = +part;
21950                   }
21951                 });
21952                 return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
21953               }
21954             }
21955
21956             return NaN;
21957           };
21958         }
21959
21960         function createDateInputType(type, regexp, parseDate, format) {
21961           return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
21962             badInputChecker(scope, element, attr, ctrl);
21963             baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
21964             var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;
21965             var previousDate;
21966
21967             ctrl.$$parserName = type;
21968             ctrl.$parsers.push(function(value) {
21969               if (ctrl.$isEmpty(value)) return null;
21970               if (regexp.test(value)) {
21971                 // Note: We cannot read ctrl.$modelValue, as there might be a different
21972                 // parser/formatter in the processing chain so that the model
21973                 // contains some different data format!
21974                 var parsedDate = parseDate(value, previousDate);
21975                 if (timezone) {
21976                   parsedDate = convertTimezoneToLocal(parsedDate, timezone);
21977                 }
21978                 return parsedDate;
21979               }
21980               return undefined;
21981             });
21982
21983             ctrl.$formatters.push(function(value) {
21984               if (value && !isDate(value)) {
21985                 throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
21986               }
21987               if (isValidDate(value)) {
21988                 previousDate = value;
21989                 if (previousDate && timezone) {
21990                   previousDate = convertTimezoneToLocal(previousDate, timezone, true);
21991                 }
21992                 return $filter('date')(value, format, timezone);
21993               } else {
21994                 previousDate = null;
21995                 return '';
21996               }
21997             });
21998
21999             if (isDefined(attr.min) || attr.ngMin) {
22000               var minVal;
22001               ctrl.$validators.min = function(value) {
22002                 return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;
22003               };
22004               attr.$observe('min', function(val) {
22005                 minVal = parseObservedDateValue(val);
22006                 ctrl.$validate();
22007               });
22008             }
22009
22010             if (isDefined(attr.max) || attr.ngMax) {
22011               var maxVal;
22012               ctrl.$validators.max = function(value) {
22013                 return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
22014               };
22015               attr.$observe('max', function(val) {
22016                 maxVal = parseObservedDateValue(val);
22017                 ctrl.$validate();
22018               });
22019             }
22020
22021             function isValidDate(value) {
22022               // Invalid Date: getTime() returns NaN
22023               return value && !(value.getTime && value.getTime() !== value.getTime());
22024             }
22025
22026             function parseObservedDateValue(val) {
22027               return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
22028             }
22029           };
22030         }
22031
22032         function badInputChecker(scope, element, attr, ctrl) {
22033           var node = element[0];
22034           var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);
22035           if (nativeValidation) {
22036             ctrl.$parsers.push(function(value) {
22037               var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
22038               // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):
22039               // - also sets validity.badInput (should only be validity.typeMismatch).
22040               // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
22041               // - can ignore this case as we can still read out the erroneous email...
22042               return validity.badInput && !validity.typeMismatch ? undefined : value;
22043             });
22044           }
22045         }
22046
22047         function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
22048           badInputChecker(scope, element, attr, ctrl);
22049           baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
22050
22051           ctrl.$$parserName = 'number';
22052           ctrl.$parsers.push(function(value) {
22053             if (ctrl.$isEmpty(value))      return null;
22054             if (NUMBER_REGEXP.test(value)) return parseFloat(value);
22055             return undefined;
22056           });
22057
22058           ctrl.$formatters.push(function(value) {
22059             if (!ctrl.$isEmpty(value)) {
22060               if (!isNumber(value)) {
22061                 throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
22062               }
22063               value = value.toString();
22064             }
22065             return value;
22066           });
22067
22068           if (isDefined(attr.min) || attr.ngMin) {
22069             var minVal;
22070             ctrl.$validators.min = function(value) {
22071               return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
22072             };
22073
22074             attr.$observe('min', function(val) {
22075               if (isDefined(val) && !isNumber(val)) {
22076                 val = parseFloat(val, 10);
22077               }
22078               minVal = isNumber(val) && !isNaN(val) ? val : undefined;
22079               // TODO(matsko): implement validateLater to reduce number of validations
22080               ctrl.$validate();
22081             });
22082           }
22083
22084           if (isDefined(attr.max) || attr.ngMax) {
22085             var maxVal;
22086             ctrl.$validators.max = function(value) {
22087               return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
22088             };
22089
22090             attr.$observe('max', function(val) {
22091               if (isDefined(val) && !isNumber(val)) {
22092                 val = parseFloat(val, 10);
22093               }
22094               maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
22095               // TODO(matsko): implement validateLater to reduce number of validations
22096               ctrl.$validate();
22097             });
22098           }
22099         }
22100
22101         function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
22102           // Note: no badInputChecker here by purpose as `url` is only a validation
22103           // in browsers, i.e. we can always read out input.value even if it is not valid!
22104           baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
22105           stringBasedInputType(ctrl);
22106
22107           ctrl.$$parserName = 'url';
22108           ctrl.$validators.url = function(modelValue, viewValue) {
22109             var value = modelValue || viewValue;
22110             return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
22111           };
22112         }
22113
22114         function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
22115           // Note: no badInputChecker here by purpose as `url` is only a validation
22116           // in browsers, i.e. we can always read out input.value even if it is not valid!
22117           baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
22118           stringBasedInputType(ctrl);
22119
22120           ctrl.$$parserName = 'email';
22121           ctrl.$validators.email = function(modelValue, viewValue) {
22122             var value = modelValue || viewValue;
22123             return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
22124           };
22125         }
22126
22127         function radioInputType(scope, element, attr, ctrl) {
22128           // make the name unique, if not defined
22129           if (isUndefined(attr.name)) {
22130             element.attr('name', nextUid());
22131           }
22132
22133           var listener = function(ev) {
22134             if (element[0].checked) {
22135               ctrl.$setViewValue(attr.value, ev && ev.type);
22136             }
22137           };
22138
22139           element.on('click', listener);
22140
22141           ctrl.$render = function() {
22142             var value = attr.value;
22143             element[0].checked = (value == ctrl.$viewValue);
22144           };
22145
22146           attr.$observe('value', ctrl.$render);
22147         }
22148
22149         function parseConstantExpr($parse, context, name, expression, fallback) {
22150           var parseFn;
22151           if (isDefined(expression)) {
22152             parseFn = $parse(expression);
22153             if (!parseFn.constant) {
22154               throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +
22155                                            '`{1}`.', name, expression);
22156             }
22157             return parseFn(context);
22158           }
22159           return fallback;
22160         }
22161
22162         function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
22163           var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
22164           var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
22165
22166           var listener = function(ev) {
22167             ctrl.$setViewValue(element[0].checked, ev && ev.type);
22168           };
22169
22170           element.on('click', listener);
22171
22172           ctrl.$render = function() {
22173             element[0].checked = ctrl.$viewValue;
22174           };
22175
22176           // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`
22177           // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert
22178           // it to a boolean.
22179           ctrl.$isEmpty = function(value) {
22180             return value === false;
22181           };
22182
22183           ctrl.$formatters.push(function(value) {
22184             return equals(value, trueValue);
22185           });
22186
22187           ctrl.$parsers.push(function(value) {
22188             return value ? trueValue : falseValue;
22189           });
22190         }
22191
22192
22193         /**
22194          * @ngdoc directive
22195          * @name textarea
22196          * @restrict E
22197          *
22198          * @description
22199          * HTML textarea element control with angular data-binding. The data-binding and validation
22200          * properties of this element are exactly the same as those of the
22201          * {@link ng.directive:input input element}.
22202          *
22203          * @param {string} ngModel Assignable angular expression to data-bind to.
22204          * @param {string=} name Property name of the form under which the control is published.
22205          * @param {string=} required Sets `required` validation error key if the value is not entered.
22206          * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
22207          *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
22208          *    `required` when you want to data-bind to the `required` attribute.
22209          * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
22210          *    minlength.
22211          * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
22212          *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
22213          *    length.
22214          * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
22215          *    a RegExp found by evaluating the Angular expression given in the attribute value.
22216          *    If the expression evaluates to a RegExp object, then this is used directly.
22217          *    If the expression evaluates to a string, then it will be converted to a RegExp
22218          *    after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
22219          *    `new RegExp('^abc$')`.<br />
22220          *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
22221          *    start at the index of the last search's match, thus not taking the whole input value into
22222          *    account.
22223          * @param {string=} ngChange Angular expression to be executed when input changes due to user
22224          *    interaction with the input element.
22225          * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
22226          */
22227
22228
22229         /**
22230          * @ngdoc directive
22231          * @name input
22232          * @restrict E
22233          *
22234          * @description
22235          * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
22236          * input state control, and validation.
22237          * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
22238          *
22239          * <div class="alert alert-warning">
22240          * **Note:** Not every feature offered is available for all input types.
22241          * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
22242          * </div>
22243          *
22244          * @param {string} ngModel Assignable angular expression to data-bind to.
22245          * @param {string=} name Property name of the form under which the control is published.
22246          * @param {string=} required Sets `required` validation error key if the value is not entered.
22247          * @param {boolean=} ngRequired Sets `required` attribute if set to true
22248          * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
22249          *    minlength.
22250          * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
22251          *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
22252          *    length.
22253          * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
22254          *    a RegExp found by evaluating the Angular expression given in the attribute value.
22255          *    If the expression evaluates to a RegExp object, then this is used directly.
22256          *    If the expression evaluates to a string, then it will be converted to a RegExp
22257          *    after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
22258          *    `new RegExp('^abc$')`.<br />
22259          *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
22260          *    start at the index of the last search's match, thus not taking the whole input value into
22261          *    account.
22262          * @param {string=} ngChange Angular expression to be executed when input changes due to user
22263          *    interaction with the input element.
22264          * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
22265          *    This parameter is ignored for input[type=password] controls, which will never trim the
22266          *    input.
22267          *
22268          * @example
22269             <example name="input-directive" module="inputExample">
22270               <file name="index.html">
22271                <script>
22272                   angular.module('inputExample', [])
22273                     .controller('ExampleController', ['$scope', function($scope) {
22274                       $scope.user = {name: 'guest', last: 'visitor'};
22275                     }]);
22276                </script>
22277                <div ng-controller="ExampleController">
22278                  <form name="myForm">
22279                    <label>
22280                       User name:
22281                       <input type="text" name="userName" ng-model="user.name" required>
22282                    </label>
22283                    <div role="alert">
22284                      <span class="error" ng-show="myForm.userName.$error.required">
22285                       Required!</span>
22286                    </div>
22287                    <label>
22288                       Last name:
22289                       <input type="text" name="lastName" ng-model="user.last"
22290                       ng-minlength="3" ng-maxlength="10">
22291                    </label>
22292                    <div role="alert">
22293                      <span class="error" ng-show="myForm.lastName.$error.minlength">
22294                        Too short!</span>
22295                      <span class="error" ng-show="myForm.lastName.$error.maxlength">
22296                        Too long!</span>
22297                    </div>
22298                  </form>
22299                  <hr>
22300                  <tt>user = {{user}}</tt><br/>
22301                  <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/>
22302                  <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/>
22303                  <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/>
22304                  <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/>
22305                  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
22306                  <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
22307                  <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/>
22308                  <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/>
22309                </div>
22310               </file>
22311               <file name="protractor.js" type="protractor">
22312                 var user = element(by.exactBinding('user'));
22313                 var userNameValid = element(by.binding('myForm.userName.$valid'));
22314                 var lastNameValid = element(by.binding('myForm.lastName.$valid'));
22315                 var lastNameError = element(by.binding('myForm.lastName.$error'));
22316                 var formValid = element(by.binding('myForm.$valid'));
22317                 var userNameInput = element(by.model('user.name'));
22318                 var userLastInput = element(by.model('user.last'));
22319
22320                 it('should initialize to model', function() {
22321                   expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
22322                   expect(userNameValid.getText()).toContain('true');
22323                   expect(formValid.getText()).toContain('true');
22324                 });
22325
22326                 it('should be invalid if empty when required', function() {
22327                   userNameInput.clear();
22328                   userNameInput.sendKeys('');
22329
22330                   expect(user.getText()).toContain('{"last":"visitor"}');
22331                   expect(userNameValid.getText()).toContain('false');
22332                   expect(formValid.getText()).toContain('false');
22333                 });
22334
22335                 it('should be valid if empty when min length is set', function() {
22336                   userLastInput.clear();
22337                   userLastInput.sendKeys('');
22338
22339                   expect(user.getText()).toContain('{"name":"guest","last":""}');
22340                   expect(lastNameValid.getText()).toContain('true');
22341                   expect(formValid.getText()).toContain('true');
22342                 });
22343
22344                 it('should be invalid if less than required min length', function() {
22345                   userLastInput.clear();
22346                   userLastInput.sendKeys('xx');
22347
22348                   expect(user.getText()).toContain('{"name":"guest"}');
22349                   expect(lastNameValid.getText()).toContain('false');
22350                   expect(lastNameError.getText()).toContain('minlength');
22351                   expect(formValid.getText()).toContain('false');
22352                 });
22353
22354                 it('should be invalid if longer than max length', function() {
22355                   userLastInput.clear();
22356                   userLastInput.sendKeys('some ridiculously long name');
22357
22358                   expect(user.getText()).toContain('{"name":"guest"}');
22359                   expect(lastNameValid.getText()).toContain('false');
22360                   expect(lastNameError.getText()).toContain('maxlength');
22361                   expect(formValid.getText()).toContain('false');
22362                 });
22363               </file>
22364             </example>
22365          */
22366         var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
22367             function($browser, $sniffer, $filter, $parse) {
22368           return {
22369             restrict: 'E',
22370             require: ['?ngModel'],
22371             link: {
22372               pre: function(scope, element, attr, ctrls) {
22373                 if (ctrls[0]) {
22374                   (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
22375                                                                       $browser, $filter, $parse);
22376                 }
22377               }
22378             }
22379           };
22380         }];
22381
22382
22383
22384         var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
22385         /**
22386          * @ngdoc directive
22387          * @name ngValue
22388          *
22389          * @description
22390          * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},
22391          * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to
22392          * the bound value.
22393          *
22394          * `ngValue` is useful when dynamically generating lists of radio buttons using
22395          * {@link ngRepeat `ngRepeat`}, as shown below.
22396          *
22397          * Likewise, `ngValue` can be used to generate `<option>` elements for
22398          * the {@link select `select`} element. In that case however, only strings are supported
22399          * for the `value `attribute, so the resulting `ngModel` will always be a string.
22400          * Support for `select` models with non-string values is available via `ngOptions`.
22401          *
22402          * @element input
22403          * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
22404          *   of the `input` element
22405          *
22406          * @example
22407             <example name="ngValue-directive" module="valueExample">
22408               <file name="index.html">
22409                <script>
22410                   angular.module('valueExample', [])
22411                     .controller('ExampleController', ['$scope', function($scope) {
22412                       $scope.names = ['pizza', 'unicorns', 'robots'];
22413                       $scope.my = { favorite: 'unicorns' };
22414                     }]);
22415                </script>
22416                 <form ng-controller="ExampleController">
22417                   <h2>Which is your favorite?</h2>
22418                     <label ng-repeat="name in names" for="{{name}}">
22419                       {{name}}
22420                       <input type="radio"
22421                              ng-model="my.favorite"
22422                              ng-value="name"
22423                              id="{{name}}"
22424                              name="favorite">
22425                     </label>
22426                   <div>You chose {{my.favorite}}</div>
22427                 </form>
22428               </file>
22429               <file name="protractor.js" type="protractor">
22430                 var favorite = element(by.binding('my.favorite'));
22431
22432                 it('should initialize to model', function() {
22433                   expect(favorite.getText()).toContain('unicorns');
22434                 });
22435                 it('should bind the values to the inputs', function() {
22436                   element.all(by.model('my.favorite')).get(0).click();
22437                   expect(favorite.getText()).toContain('pizza');
22438                 });
22439               </file>
22440             </example>
22441          */
22442         var ngValueDirective = function() {
22443           return {
22444             restrict: 'A',
22445             priority: 100,
22446             compile: function(tpl, tplAttr) {
22447               if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
22448                 return function ngValueConstantLink(scope, elm, attr) {
22449                   attr.$set('value', scope.$eval(attr.ngValue));
22450                 };
22451               } else {
22452                 return function ngValueLink(scope, elm, attr) {
22453                   scope.$watch(attr.ngValue, function valueWatchAction(value) {
22454                     attr.$set('value', value);
22455                   });
22456                 };
22457               }
22458             }
22459           };
22460         };
22461
22462         /**
22463          * @ngdoc directive
22464          * @name ngBind
22465          * @restrict AC
22466          *
22467          * @description
22468          * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
22469          * with the value of a given expression, and to update the text content when the value of that
22470          * expression changes.
22471          *
22472          * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
22473          * `{{ expression }}` which is similar but less verbose.
22474          *
22475          * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
22476          * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
22477          * element attribute, it makes the bindings invisible to the user while the page is loading.
22478          *
22479          * An alternative solution to this problem would be using the
22480          * {@link ng.directive:ngCloak ngCloak} directive.
22481          *
22482          *
22483          * @element ANY
22484          * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
22485          *
22486          * @example
22487          * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
22488            <example module="bindExample">
22489              <file name="index.html">
22490                <script>
22491                  angular.module('bindExample', [])
22492                    .controller('ExampleController', ['$scope', function($scope) {
22493                      $scope.name = 'Whirled';
22494                    }]);
22495                </script>
22496                <div ng-controller="ExampleController">
22497                  <label>Enter name: <input type="text" ng-model="name"></label><br>
22498                  Hello <span ng-bind="name"></span>!
22499                </div>
22500              </file>
22501              <file name="protractor.js" type="protractor">
22502                it('should check ng-bind', function() {
22503                  var nameInput = element(by.model('name'));
22504
22505                  expect(element(by.binding('name')).getText()).toBe('Whirled');
22506                  nameInput.clear();
22507                  nameInput.sendKeys('world');
22508                  expect(element(by.binding('name')).getText()).toBe('world');
22509                });
22510              </file>
22511            </example>
22512          */
22513         var ngBindDirective = ['$compile', function($compile) {
22514           return {
22515             restrict: 'AC',
22516             compile: function ngBindCompile(templateElement) {
22517               $compile.$$addBindingClass(templateElement);
22518               return function ngBindLink(scope, element, attr) {
22519                 $compile.$$addBindingInfo(element, attr.ngBind);
22520                 element = element[0];
22521                 scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
22522                   element.textContent = isUndefined(value) ? '' : value;
22523                 });
22524               };
22525             }
22526           };
22527         }];
22528
22529
22530         /**
22531          * @ngdoc directive
22532          * @name ngBindTemplate
22533          *
22534          * @description
22535          * The `ngBindTemplate` directive specifies that the element
22536          * text content should be replaced with the interpolation of the template
22537          * in the `ngBindTemplate` attribute.
22538          * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
22539          * expressions. This directive is needed since some HTML elements
22540          * (such as TITLE and OPTION) cannot contain SPAN elements.
22541          *
22542          * @element ANY
22543          * @param {string} ngBindTemplate template of form
22544          *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
22545          *
22546          * @example
22547          * Try it here: enter text in text box and watch the greeting change.
22548            <example module="bindExample">
22549              <file name="index.html">
22550                <script>
22551                  angular.module('bindExample', [])
22552                    .controller('ExampleController', ['$scope', function($scope) {
22553                      $scope.salutation = 'Hello';
22554                      $scope.name = 'World';
22555                    }]);
22556                </script>
22557                <div ng-controller="ExampleController">
22558                 <label>Salutation: <input type="text" ng-model="salutation"></label><br>
22559                 <label>Name: <input type="text" ng-model="name"></label><br>
22560                 <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
22561                </div>
22562              </file>
22563              <file name="protractor.js" type="protractor">
22564                it('should check ng-bind', function() {
22565                  var salutationElem = element(by.binding('salutation'));
22566                  var salutationInput = element(by.model('salutation'));
22567                  var nameInput = element(by.model('name'));
22568
22569                  expect(salutationElem.getText()).toBe('Hello World!');
22570
22571                  salutationInput.clear();
22572                  salutationInput.sendKeys('Greetings');
22573                  nameInput.clear();
22574                  nameInput.sendKeys('user');
22575
22576                  expect(salutationElem.getText()).toBe('Greetings user!');
22577                });
22578              </file>
22579            </example>
22580          */
22581         var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {
22582           return {
22583             compile: function ngBindTemplateCompile(templateElement) {
22584               $compile.$$addBindingClass(templateElement);
22585               return function ngBindTemplateLink(scope, element, attr) {
22586                 var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
22587                 $compile.$$addBindingInfo(element, interpolateFn.expressions);
22588                 element = element[0];
22589                 attr.$observe('ngBindTemplate', function(value) {
22590                   element.textContent = isUndefined(value) ? '' : value;
22591                 });
22592               };
22593             }
22594           };
22595         }];
22596
22597
22598         /**
22599          * @ngdoc directive
22600          * @name ngBindHtml
22601          *
22602          * @description
22603          * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
22604          * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
22605          * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
22606          * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
22607          * in your module's dependencies, you need to include "angular-sanitize.js" in your application.
22608          *
22609          * You may also bypass sanitization for values you know are safe. To do so, bind to
22610          * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example
22611          * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.
22612          *
22613          * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
22614          * will have an exception (instead of an exploit.)
22615          *
22616          * @element ANY
22617          * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
22618          *
22619          * @example
22620
22621            <example module="bindHtmlExample" deps="angular-sanitize.js">
22622              <file name="index.html">
22623                <div ng-controller="ExampleController">
22624                 <p ng-bind-html="myHTML"></p>
22625                </div>
22626              </file>
22627
22628              <file name="script.js">
22629                angular.module('bindHtmlExample', ['ngSanitize'])
22630                  .controller('ExampleController', ['$scope', function($scope) {
22631                    $scope.myHTML =
22632                       'I am an <code>HTML</code>string with ' +
22633                       '<a href="#">links!</a> and other <em>stuff</em>';
22634                  }]);
22635              </file>
22636
22637              <file name="protractor.js" type="protractor">
22638                it('should check ng-bind-html', function() {
22639                  expect(element(by.binding('myHTML')).getText()).toBe(
22640                      'I am an HTMLstring with links! and other stuff');
22641                });
22642              </file>
22643            </example>
22644          */
22645         var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
22646           return {
22647             restrict: 'A',
22648             compile: function ngBindHtmlCompile(tElement, tAttrs) {
22649               var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
22650               var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
22651                 return (value || '').toString();
22652               });
22653               $compile.$$addBindingClass(tElement);
22654
22655               return function ngBindHtmlLink(scope, element, attr) {
22656                 $compile.$$addBindingInfo(element, attr.ngBindHtml);
22657
22658                 scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
22659                   // we re-evaluate the expr because we want a TrustedValueHolderType
22660                   // for $sce, not a string
22661                   element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
22662                 });
22663               };
22664             }
22665           };
22666         }];
22667
22668         /**
22669          * @ngdoc directive
22670          * @name ngChange
22671          *
22672          * @description
22673          * Evaluate the given expression when the user changes the input.
22674          * The expression is evaluated immediately, unlike the JavaScript onchange event
22675          * which only triggers at the end of a change (usually, when the user leaves the
22676          * form element or presses the return key).
22677          *
22678          * The `ngChange` expression is only evaluated when a change in the input value causes
22679          * a new value to be committed to the model.
22680          *
22681          * It will not be evaluated:
22682          * * if the value returned from the `$parsers` transformation pipeline has not changed
22683          * * if the input has continued to be invalid since the model will stay `null`
22684          * * if the model is changed programmatically and not by a change to the input value
22685          *
22686          *
22687          * Note, this directive requires `ngModel` to be present.
22688          *
22689          * @element input
22690          * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
22691          * in input value.
22692          *
22693          * @example
22694          * <example name="ngChange-directive" module="changeExample">
22695          *   <file name="index.html">
22696          *     <script>
22697          *       angular.module('changeExample', [])
22698          *         .controller('ExampleController', ['$scope', function($scope) {
22699          *           $scope.counter = 0;
22700          *           $scope.change = function() {
22701          *             $scope.counter++;
22702          *           };
22703          *         }]);
22704          *     </script>
22705          *     <div ng-controller="ExampleController">
22706          *       <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
22707          *       <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
22708          *       <label for="ng-change-example2">Confirmed</label><br />
22709          *       <tt>debug = {{confirmed}}</tt><br/>
22710          *       <tt>counter = {{counter}}</tt><br/>
22711          *     </div>
22712          *   </file>
22713          *   <file name="protractor.js" type="protractor">
22714          *     var counter = element(by.binding('counter'));
22715          *     var debug = element(by.binding('confirmed'));
22716          *
22717          *     it('should evaluate the expression if changing from view', function() {
22718          *       expect(counter.getText()).toContain('0');
22719          *
22720          *       element(by.id('ng-change-example1')).click();
22721          *
22722          *       expect(counter.getText()).toContain('1');
22723          *       expect(debug.getText()).toContain('true');
22724          *     });
22725          *
22726          *     it('should not evaluate the expression if changing from model', function() {
22727          *       element(by.id('ng-change-example2')).click();
22728
22729          *       expect(counter.getText()).toContain('0');
22730          *       expect(debug.getText()).toContain('true');
22731          *     });
22732          *   </file>
22733          * </example>
22734          */
22735         var ngChangeDirective = valueFn({
22736           restrict: 'A',
22737           require: 'ngModel',
22738           link: function(scope, element, attr, ctrl) {
22739             ctrl.$viewChangeListeners.push(function() {
22740               scope.$eval(attr.ngChange);
22741             });
22742           }
22743         });
22744
22745         function classDirective(name, selector) {
22746           name = 'ngClass' + name;
22747           return ['$animate', function($animate) {
22748             return {
22749               restrict: 'AC',
22750               link: function(scope, element, attr) {
22751                 var oldVal;
22752
22753                 scope.$watch(attr[name], ngClassWatchAction, true);
22754
22755                 attr.$observe('class', function(value) {
22756                   ngClassWatchAction(scope.$eval(attr[name]));
22757                 });
22758
22759
22760                 if (name !== 'ngClass') {
22761                   scope.$watch('$index', function($index, old$index) {
22762                     // jshint bitwise: false
22763                     var mod = $index & 1;
22764                     if (mod !== (old$index & 1)) {
22765                       var classes = arrayClasses(scope.$eval(attr[name]));
22766                       mod === selector ?
22767                         addClasses(classes) :
22768                         removeClasses(classes);
22769                     }
22770                   });
22771                 }
22772
22773                 function addClasses(classes) {
22774                   var newClasses = digestClassCounts(classes, 1);
22775                   attr.$addClass(newClasses);
22776                 }
22777
22778                 function removeClasses(classes) {
22779                   var newClasses = digestClassCounts(classes, -1);
22780                   attr.$removeClass(newClasses);
22781                 }
22782
22783                 function digestClassCounts(classes, count) {
22784                   // Use createMap() to prevent class assumptions involving property
22785                   // names in Object.prototype
22786                   var classCounts = element.data('$classCounts') || createMap();
22787                   var classesToUpdate = [];
22788                   forEach(classes, function(className) {
22789                     if (count > 0 || classCounts[className]) {
22790                       classCounts[className] = (classCounts[className] || 0) + count;
22791                       if (classCounts[className] === +(count > 0)) {
22792                         classesToUpdate.push(className);
22793                       }
22794                     }
22795                   });
22796                   element.data('$classCounts', classCounts);
22797                   return classesToUpdate.join(' ');
22798                 }
22799
22800                 function updateClasses(oldClasses, newClasses) {
22801                   var toAdd = arrayDifference(newClasses, oldClasses);
22802                   var toRemove = arrayDifference(oldClasses, newClasses);
22803                   toAdd = digestClassCounts(toAdd, 1);
22804                   toRemove = digestClassCounts(toRemove, -1);
22805                   if (toAdd && toAdd.length) {
22806                     $animate.addClass(element, toAdd);
22807                   }
22808                   if (toRemove && toRemove.length) {
22809                     $animate.removeClass(element, toRemove);
22810                   }
22811                 }
22812
22813                 function ngClassWatchAction(newVal) {
22814                   if (selector === true || scope.$index % 2 === selector) {
22815                     var newClasses = arrayClasses(newVal || []);
22816                     if (!oldVal) {
22817                       addClasses(newClasses);
22818                     } else if (!equals(newVal,oldVal)) {
22819                       var oldClasses = arrayClasses(oldVal);
22820                       updateClasses(oldClasses, newClasses);
22821                     }
22822                   }
22823                   oldVal = shallowCopy(newVal);
22824                 }
22825               }
22826             };
22827
22828             function arrayDifference(tokens1, tokens2) {
22829               var values = [];
22830
22831               outer:
22832               for (var i = 0; i < tokens1.length; i++) {
22833                 var token = tokens1[i];
22834                 for (var j = 0; j < tokens2.length; j++) {
22835                   if (token == tokens2[j]) continue outer;
22836                 }
22837                 values.push(token);
22838               }
22839               return values;
22840             }
22841
22842             function arrayClasses(classVal) {
22843               var classes = [];
22844               if (isArray(classVal)) {
22845                 forEach(classVal, function(v) {
22846                   classes = classes.concat(arrayClasses(v));
22847                 });
22848                 return classes;
22849               } else if (isString(classVal)) {
22850                 return classVal.split(' ');
22851               } else if (isObject(classVal)) {
22852                 forEach(classVal, function(v, k) {
22853                   if (v) {
22854                     classes = classes.concat(k.split(' '));
22855                   }
22856                 });
22857                 return classes;
22858               }
22859               return classVal;
22860             }
22861           }];
22862         }
22863
22864         /**
22865          * @ngdoc directive
22866          * @name ngClass
22867          * @restrict AC
22868          *
22869          * @description
22870          * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
22871          * an expression that represents all classes to be added.
22872          *
22873          * The directive operates in three different ways, depending on which of three types the expression
22874          * evaluates to:
22875          *
22876          * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
22877          * names.
22878          *
22879          * 2. If the expression evaluates to an object, then for each key-value pair of the
22880          * object with a truthy value the corresponding key is used as a class name.
22881          *
22882          * 3. If the expression evaluates to an array, each element of the array should either be a string as in
22883          * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array
22884          * to give you more control over what CSS classes appear. See the code below for an example of this.
22885          *
22886          *
22887          * The directive won't add duplicate classes if a particular class was already set.
22888          *
22889          * When the expression changes, the previously added classes are removed and only then are the
22890          * new classes added.
22891          *
22892          * @animations
22893          * **add** - happens just before the class is applied to the elements
22894          *
22895          * **remove** - happens just before the class is removed from the element
22896          *
22897          * @element ANY
22898          * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
22899          *   of the evaluation can be a string representing space delimited class
22900          *   names, an array, or a map of class names to boolean values. In the case of a map, the
22901          *   names of the properties whose values are truthy will be added as css classes to the
22902          *   element.
22903          *
22904          * @example Example that demonstrates basic bindings via ngClass directive.
22905            <example>
22906              <file name="index.html">
22907                <p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p>
22908                <label>
22909                   <input type="checkbox" ng-model="deleted">
22910                   deleted (apply "strike" class)
22911                </label><br>
22912                <label>
22913                   <input type="checkbox" ng-model="important">
22914                   important (apply "bold" class)
22915                </label><br>
22916                <label>
22917                   <input type="checkbox" ng-model="error">
22918                   error (apply "has-error" class)
22919                </label>
22920                <hr>
22921                <p ng-class="style">Using String Syntax</p>
22922                <input type="text" ng-model="style"
22923                       placeholder="Type: bold strike red" aria-label="Type: bold strike red">
22924                <hr>
22925                <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
22926                <input ng-model="style1"
22927                       placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red"><br>
22928                <input ng-model="style2"
22929                       placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 2"><br>
22930                <input ng-model="style3"
22931                       placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 3"><br>
22932                <hr>
22933                <p ng-class="[style4, {orange: warning}]">Using Array and Map Syntax</p>
22934                <input ng-model="style4" placeholder="Type: bold, strike" aria-label="Type: bold, strike"><br>
22935                <label><input type="checkbox" ng-model="warning"> warning (apply "orange" class)</label>
22936              </file>
22937              <file name="style.css">
22938                .strike {
22939                    text-decoration: line-through;
22940                }
22941                .bold {
22942                    font-weight: bold;
22943                }
22944                .red {
22945                    color: red;
22946                }
22947                .has-error {
22948                    color: red;
22949                    background-color: yellow;
22950                }
22951                .orange {
22952                    color: orange;
22953                }
22954              </file>
22955              <file name="protractor.js" type="protractor">
22956                var ps = element.all(by.css('p'));
22957
22958                it('should let you toggle the class', function() {
22959
22960                  expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
22961                  expect(ps.first().getAttribute('class')).not.toMatch(/has-error/);
22962
22963                  element(by.model('important')).click();
22964                  expect(ps.first().getAttribute('class')).toMatch(/bold/);
22965
22966                  element(by.model('error')).click();
22967                  expect(ps.first().getAttribute('class')).toMatch(/has-error/);
22968                });
22969
22970                it('should let you toggle string example', function() {
22971                  expect(ps.get(1).getAttribute('class')).toBe('');
22972                  element(by.model('style')).clear();
22973                  element(by.model('style')).sendKeys('red');
22974                  expect(ps.get(1).getAttribute('class')).toBe('red');
22975                });
22976
22977                it('array example should have 3 classes', function() {
22978                  expect(ps.get(2).getAttribute('class')).toBe('');
22979                  element(by.model('style1')).sendKeys('bold');
22980                  element(by.model('style2')).sendKeys('strike');
22981                  element(by.model('style3')).sendKeys('red');
22982                  expect(ps.get(2).getAttribute('class')).toBe('bold strike red');
22983                });
22984
22985                it('array with map example should have 2 classes', function() {
22986                  expect(ps.last().getAttribute('class')).toBe('');
22987                  element(by.model('style4')).sendKeys('bold');
22988                  element(by.model('warning')).click();
22989                  expect(ps.last().getAttribute('class')).toBe('bold orange');
22990                });
22991              </file>
22992            </example>
22993
22994            ## Animations
22995
22996            The example below demonstrates how to perform animations using ngClass.
22997
22998            <example module="ngAnimate" deps="angular-animate.js" animations="true">
22999              <file name="index.html">
23000               <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
23001               <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
23002               <br>
23003               <span class="base-class" ng-class="myVar">Sample Text</span>
23004              </file>
23005              <file name="style.css">
23006                .base-class {
23007                  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
23008                }
23009
23010                .base-class.my-class {
23011                  color: red;
23012                  font-size:3em;
23013                }
23014              </file>
23015              <file name="protractor.js" type="protractor">
23016                it('should check ng-class', function() {
23017                  expect(element(by.css('.base-class')).getAttribute('class')).not.
23018                    toMatch(/my-class/);
23019
23020                  element(by.id('setbtn')).click();
23021
23022                  expect(element(by.css('.base-class')).getAttribute('class')).
23023                    toMatch(/my-class/);
23024
23025                  element(by.id('clearbtn')).click();
23026
23027                  expect(element(by.css('.base-class')).getAttribute('class')).not.
23028                    toMatch(/my-class/);
23029                });
23030              </file>
23031            </example>
23032
23033
23034            ## ngClass and pre-existing CSS3 Transitions/Animations
23035            The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
23036            Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
23037            any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
23038            to view the step by step details of {@link $animate#addClass $animate.addClass} and
23039            {@link $animate#removeClass $animate.removeClass}.
23040          */
23041         var ngClassDirective = classDirective('', true);
23042
23043         /**
23044          * @ngdoc directive
23045          * @name ngClassOdd
23046          * @restrict AC
23047          *
23048          * @description
23049          * The `ngClassOdd` and `ngClassEven` directives work exactly as
23050          * {@link ng.directive:ngClass ngClass}, except they work in
23051          * conjunction with `ngRepeat` and take effect only on odd (even) rows.
23052          *
23053          * This directive can be applied only within the scope of an
23054          * {@link ng.directive:ngRepeat ngRepeat}.
23055          *
23056          * @element ANY
23057          * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
23058          *   of the evaluation can be a string representing space delimited class names or an array.
23059          *
23060          * @example
23061            <example>
23062              <file name="index.html">
23063                 <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
23064                   <li ng-repeat="name in names">
23065                    <span ng-class-odd="'odd'" ng-class-even="'even'">
23066                      {{name}}
23067                    </span>
23068                   </li>
23069                 </ol>
23070              </file>
23071              <file name="style.css">
23072                .odd {
23073                  color: red;
23074                }
23075                .even {
23076                  color: blue;
23077                }
23078              </file>
23079              <file name="protractor.js" type="protractor">
23080                it('should check ng-class-odd and ng-class-even', function() {
23081                  expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
23082                    toMatch(/odd/);
23083                  expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
23084                    toMatch(/even/);
23085                });
23086              </file>
23087            </example>
23088          */
23089         var ngClassOddDirective = classDirective('Odd', 0);
23090
23091         /**
23092          * @ngdoc directive
23093          * @name ngClassEven
23094          * @restrict AC
23095          *
23096          * @description
23097          * The `ngClassOdd` and `ngClassEven` directives work exactly as
23098          * {@link ng.directive:ngClass ngClass}, except they work in
23099          * conjunction with `ngRepeat` and take effect only on odd (even) rows.
23100          *
23101          * This directive can be applied only within the scope of an
23102          * {@link ng.directive:ngRepeat ngRepeat}.
23103          *
23104          * @element ANY
23105          * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
23106          *   result of the evaluation can be a string representing space delimited class names or an array.
23107          *
23108          * @example
23109            <example>
23110              <file name="index.html">
23111                 <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
23112                   <li ng-repeat="name in names">
23113                    <span ng-class-odd="'odd'" ng-class-even="'even'">
23114                      {{name}} &nbsp; &nbsp; &nbsp;
23115                    </span>
23116                   </li>
23117                 </ol>
23118              </file>
23119              <file name="style.css">
23120                .odd {
23121                  color: red;
23122                }
23123                .even {
23124                  color: blue;
23125                }
23126              </file>
23127              <file name="protractor.js" type="protractor">
23128                it('should check ng-class-odd and ng-class-even', function() {
23129                  expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
23130                    toMatch(/odd/);
23131                  expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
23132                    toMatch(/even/);
23133                });
23134              </file>
23135            </example>
23136          */
23137         var ngClassEvenDirective = classDirective('Even', 1);
23138
23139         /**
23140          * @ngdoc directive
23141          * @name ngCloak
23142          * @restrict AC
23143          *
23144          * @description
23145          * The `ngCloak` directive is used to prevent the Angular html template from being briefly
23146          * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
23147          * directive to avoid the undesirable flicker effect caused by the html template display.
23148          *
23149          * The directive can be applied to the `<body>` element, but the preferred usage is to apply
23150          * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
23151          * of the browser view.
23152          *
23153          * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
23154          * `angular.min.js`.
23155          * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
23156          *
23157          * ```css
23158          * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
23159          *   display: none !important;
23160          * }
23161          * ```
23162          *
23163          * When this css rule is loaded by the browser, all html elements (including their children) that
23164          * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
23165          * during the compilation of the template it deletes the `ngCloak` element attribute, making
23166          * the compiled element visible.
23167          *
23168          * For the best result, the `angular.js` script must be loaded in the head section of the html
23169          * document; alternatively, the css rule above must be included in the external stylesheet of the
23170          * application.
23171          *
23172          * @element ANY
23173          *
23174          * @example
23175            <example>
23176              <file name="index.html">
23177                 <div id="template1" ng-cloak>{{ 'hello' }}</div>
23178                 <div id="template2" class="ng-cloak">{{ 'world' }}</div>
23179              </file>
23180              <file name="protractor.js" type="protractor">
23181                it('should remove the template directive and css class', function() {
23182                  expect($('#template1').getAttribute('ng-cloak')).
23183                    toBeNull();
23184                  expect($('#template2').getAttribute('ng-cloak')).
23185                    toBeNull();
23186                });
23187              </file>
23188            </example>
23189          *
23190          */
23191         var ngCloakDirective = ngDirective({
23192           compile: function(element, attr) {
23193             attr.$set('ngCloak', undefined);
23194             element.removeClass('ng-cloak');
23195           }
23196         });
23197
23198         /**
23199          * @ngdoc directive
23200          * @name ngController
23201          *
23202          * @description
23203          * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
23204          * supports the principles behind the Model-View-Controller design pattern.
23205          *
23206          * MVC components in angular:
23207          *
23208          * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
23209          *   are accessed through bindings.
23210          * * View — The template (HTML with data bindings) that is rendered into the View.
23211          * * Controller — The `ngController` directive specifies a Controller class; the class contains business
23212          *   logic behind the application to decorate the scope with functions and values
23213          *
23214          * Note that you can also attach controllers to the DOM by declaring it in a route definition
23215          * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
23216          * again using `ng-controller` in the template itself.  This will cause the controller to be attached
23217          * and executed twice.
23218          *
23219          * @element ANY
23220          * @scope
23221          * @priority 500
23222          * @param {expression} ngController Name of a constructor function registered with the current
23223          * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
23224          * that on the current scope evaluates to a constructor function.
23225          *
23226          * The controller instance can be published into a scope property by specifying
23227          * `ng-controller="as propertyName"`.
23228          *
23229          * If the current `$controllerProvider` is configured to use globals (via
23230          * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
23231          * also be the name of a globally accessible constructor function (not recommended).
23232          *
23233          * @example
23234          * Here is a simple form for editing user contact information. Adding, removing, clearing, and
23235          * greeting are methods declared on the controller (see source tab). These methods can
23236          * easily be called from the angular markup. Any changes to the data are automatically reflected
23237          * in the View without the need for a manual update.
23238          *
23239          * Two different declaration styles are included below:
23240          *
23241          * * one binds methods and properties directly onto the controller using `this`:
23242          * `ng-controller="SettingsController1 as settings"`
23243          * * one injects `$scope` into the controller:
23244          * `ng-controller="SettingsController2"`
23245          *
23246          * The second option is more common in the Angular community, and is generally used in boilerplates
23247          * and in this guide. However, there are advantages to binding properties directly to the controller
23248          * and avoiding scope.
23249          *
23250          * * Using `controller as` makes it obvious which controller you are accessing in the template when
23251          * multiple controllers apply to an element.
23252          * * If you are writing your controllers as classes you have easier access to the properties and
23253          * methods, which will appear on the scope, from inside the controller code.
23254          * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
23255          * inheritance masking primitives.
23256          *
23257          * This example demonstrates the `controller as` syntax.
23258          *
23259          * <example name="ngControllerAs" module="controllerAsExample">
23260          *   <file name="index.html">
23261          *    <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
23262          *      <label>Name: <input type="text" ng-model="settings.name"/></label>
23263          *      <button ng-click="settings.greet()">greet</button><br/>
23264          *      Contact:
23265          *      <ul>
23266          *        <li ng-repeat="contact in settings.contacts">
23267          *          <select ng-model="contact.type" aria-label="Contact method" id="select_{{$index}}">
23268          *             <option>phone</option>
23269          *             <option>email</option>
23270          *          </select>
23271          *          <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
23272          *          <button ng-click="settings.clearContact(contact)">clear</button>
23273          *          <button ng-click="settings.removeContact(contact)" aria-label="Remove">X</button>
23274          *        </li>
23275          *        <li><button ng-click="settings.addContact()">add</button></li>
23276          *     </ul>
23277          *    </div>
23278          *   </file>
23279          *   <file name="app.js">
23280          *    angular.module('controllerAsExample', [])
23281          *      .controller('SettingsController1', SettingsController1);
23282          *
23283          *    function SettingsController1() {
23284          *      this.name = "John Smith";
23285          *      this.contacts = [
23286          *        {type: 'phone', value: '408 555 1212'},
23287          *        {type: 'email', value: 'john.smith@example.org'} ];
23288          *    }
23289          *
23290          *    SettingsController1.prototype.greet = function() {
23291          *      alert(this.name);
23292          *    };
23293          *
23294          *    SettingsController1.prototype.addContact = function() {
23295          *      this.contacts.push({type: 'email', value: 'yourname@example.org'});
23296          *    };
23297          *
23298          *    SettingsController1.prototype.removeContact = function(contactToRemove) {
23299          *     var index = this.contacts.indexOf(contactToRemove);
23300          *      this.contacts.splice(index, 1);
23301          *    };
23302          *
23303          *    SettingsController1.prototype.clearContact = function(contact) {
23304          *      contact.type = 'phone';
23305          *      contact.value = '';
23306          *    };
23307          *   </file>
23308          *   <file name="protractor.js" type="protractor">
23309          *     it('should check controller as', function() {
23310          *       var container = element(by.id('ctrl-as-exmpl'));
23311          *         expect(container.element(by.model('settings.name'))
23312          *           .getAttribute('value')).toBe('John Smith');
23313          *
23314          *       var firstRepeat =
23315          *           container.element(by.repeater('contact in settings.contacts').row(0));
23316          *       var secondRepeat =
23317          *           container.element(by.repeater('contact in settings.contacts').row(1));
23318          *
23319          *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
23320          *           .toBe('408 555 1212');
23321          *
23322          *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
23323          *           .toBe('john.smith@example.org');
23324          *
23325          *       firstRepeat.element(by.buttonText('clear')).click();
23326          *
23327          *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
23328          *           .toBe('');
23329          *
23330          *       container.element(by.buttonText('add')).click();
23331          *
23332          *       expect(container.element(by.repeater('contact in settings.contacts').row(2))
23333          *           .element(by.model('contact.value'))
23334          *           .getAttribute('value'))
23335          *           .toBe('yourname@example.org');
23336          *     });
23337          *   </file>
23338          * </example>
23339          *
23340          * This example demonstrates the "attach to `$scope`" style of controller.
23341          *
23342          * <example name="ngController" module="controllerExample">
23343          *  <file name="index.html">
23344          *   <div id="ctrl-exmpl" ng-controller="SettingsController2">
23345          *     <label>Name: <input type="text" ng-model="name"/></label>
23346          *     <button ng-click="greet()">greet</button><br/>
23347          *     Contact:
23348          *     <ul>
23349          *       <li ng-repeat="contact in contacts">
23350          *         <select ng-model="contact.type" id="select_{{$index}}">
23351          *            <option>phone</option>
23352          *            <option>email</option>
23353          *         </select>
23354          *         <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
23355          *         <button ng-click="clearContact(contact)">clear</button>
23356          *         <button ng-click="removeContact(contact)">X</button>
23357          *       </li>
23358          *       <li>[ <button ng-click="addContact()">add</button> ]</li>
23359          *    </ul>
23360          *   </div>
23361          *  </file>
23362          *  <file name="app.js">
23363          *   angular.module('controllerExample', [])
23364          *     .controller('SettingsController2', ['$scope', SettingsController2]);
23365          *
23366          *   function SettingsController2($scope) {
23367          *     $scope.name = "John Smith";
23368          *     $scope.contacts = [
23369          *       {type:'phone', value:'408 555 1212'},
23370          *       {type:'email', value:'john.smith@example.org'} ];
23371          *
23372          *     $scope.greet = function() {
23373          *       alert($scope.name);
23374          *     };
23375          *
23376          *     $scope.addContact = function() {
23377          *       $scope.contacts.push({type:'email', value:'yourname@example.org'});
23378          *     };
23379          *
23380          *     $scope.removeContact = function(contactToRemove) {
23381          *       var index = $scope.contacts.indexOf(contactToRemove);
23382          *       $scope.contacts.splice(index, 1);
23383          *     };
23384          *
23385          *     $scope.clearContact = function(contact) {
23386          *       contact.type = 'phone';
23387          *       contact.value = '';
23388          *     };
23389          *   }
23390          *  </file>
23391          *  <file name="protractor.js" type="protractor">
23392          *    it('should check controller', function() {
23393          *      var container = element(by.id('ctrl-exmpl'));
23394          *
23395          *      expect(container.element(by.model('name'))
23396          *          .getAttribute('value')).toBe('John Smith');
23397          *
23398          *      var firstRepeat =
23399          *          container.element(by.repeater('contact in contacts').row(0));
23400          *      var secondRepeat =
23401          *          container.element(by.repeater('contact in contacts').row(1));
23402          *
23403          *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
23404          *          .toBe('408 555 1212');
23405          *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
23406          *          .toBe('john.smith@example.org');
23407          *
23408          *      firstRepeat.element(by.buttonText('clear')).click();
23409          *
23410          *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
23411          *          .toBe('');
23412          *
23413          *      container.element(by.buttonText('add')).click();
23414          *
23415          *      expect(container.element(by.repeater('contact in contacts').row(2))
23416          *          .element(by.model('contact.value'))
23417          *          .getAttribute('value'))
23418          *          .toBe('yourname@example.org');
23419          *    });
23420          *  </file>
23421          *</example>
23422
23423          */
23424         var ngControllerDirective = [function() {
23425           return {
23426             restrict: 'A',
23427             scope: true,
23428             controller: '@',
23429             priority: 500
23430           };
23431         }];
23432
23433         /**
23434          * @ngdoc directive
23435          * @name ngCsp
23436          *
23437          * @element html
23438          * @description
23439          *
23440          * Angular has some features that can break certain
23441          * [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules.
23442          *
23443          * If you intend to implement these rules then you must tell Angular not to use these features.
23444          *
23445          * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
23446          *
23447          *
23448          * The following rules affect Angular:
23449          *
23450          * * `unsafe-eval`: this rule forbids apps to use `eval` or `Function(string)` generated functions
23451          * (among other things). Angular makes use of this in the {@link $parse} service to provide a 30%
23452          * increase in the speed of evaluating Angular expressions.
23453          *
23454          * * `unsafe-inline`: this rule forbids apps from inject custom styles into the document. Angular
23455          * makes use of this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}).
23456          * To make these directives work when a CSP rule is blocking inline styles, you must link to the
23457          * `angular-csp.css` in your HTML manually.
23458          *
23459          * If you do not provide `ngCsp` then Angular tries to autodetect if CSP is blocking unsafe-eval
23460          * and automatically deactivates this feature in the {@link $parse} service. This autodetection,
23461          * however, triggers a CSP error to be logged in the console:
23462          *
23463          * ```
23464          * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
23465          * script in the following Content Security Policy directive: "default-src 'self'". Note that
23466          * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
23467          * ```
23468          *
23469          * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
23470          * directive on an element of the HTML document that appears before the `<script>` tag that loads
23471          * the `angular.js` file.
23472          *
23473          * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
23474          *
23475          * You can specify which of the CSP related Angular features should be deactivated by providing
23476          * a value for the `ng-csp` attribute. The options are as follows:
23477          *
23478          * * no-inline-style: this stops Angular from injecting CSS styles into the DOM
23479          *
23480          * * no-unsafe-eval: this stops Angular from optimising $parse with unsafe eval of strings
23481          *
23482          * You can use these values in the following combinations:
23483          *
23484          *
23485          * * No declaration means that Angular will assume that you can do inline styles, but it will do
23486          * a runtime check for unsafe-eval. E.g. `<body>`. This is backwardly compatible with previous versions
23487          * of Angular.
23488          *
23489          * * A simple `ng-csp` (or `data-ng-csp`) attribute will tell Angular to deactivate both inline
23490          * styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous versions
23491          * of Angular.
23492          *
23493          * * Specifying only `no-unsafe-eval` tells Angular that we must not use eval, but that we can inject
23494          * inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
23495          *
23496          * * Specifying only `no-inline-style` tells Angular that we must not inject styles, but that we can
23497          * run eval - no automcatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
23498          *
23499          * * Specifying both `no-unsafe-eval` and `no-inline-style` tells Angular that we must not inject
23500          * styles nor use eval, which is the same as an empty: ng-csp.
23501          * E.g.`<body ng-csp="no-inline-style;no-unsafe-eval">`
23502          *
23503          * @example
23504          * This example shows how to apply the `ngCsp` directive to the `html` tag.
23505            ```html
23506              <!doctype html>
23507              <html ng-app ng-csp>
23508              ...
23509              ...
23510              </html>
23511            ```
23512           * @example
23513               // Note: the suffix `.csp` in the example name triggers
23514               // csp mode in our http server!
23515               <example name="example.csp" module="cspExample" ng-csp="true">
23516                 <file name="index.html">
23517                   <div ng-controller="MainController as ctrl">
23518                     <div>
23519                       <button ng-click="ctrl.inc()" id="inc">Increment</button>
23520                       <span id="counter">
23521                         {{ctrl.counter}}
23522                       </span>
23523                     </div>
23524
23525                     <div>
23526                       <button ng-click="ctrl.evil()" id="evil">Evil</button>
23527                       <span id="evilError">
23528                         {{ctrl.evilError}}
23529                       </span>
23530                     </div>
23531                   </div>
23532                 </file>
23533                 <file name="script.js">
23534                    angular.module('cspExample', [])
23535                      .controller('MainController', function() {
23536                         this.counter = 0;
23537                         this.inc = function() {
23538                           this.counter++;
23539                         };
23540                         this.evil = function() {
23541                           // jshint evil:true
23542                           try {
23543                             eval('1+2');
23544                           } catch (e) {
23545                             this.evilError = e.message;
23546                           }
23547                         };
23548                       });
23549                 </file>
23550                 <file name="protractor.js" type="protractor">
23551                   var util, webdriver;
23552
23553                   var incBtn = element(by.id('inc'));
23554                   var counter = element(by.id('counter'));
23555                   var evilBtn = element(by.id('evil'));
23556                   var evilError = element(by.id('evilError'));
23557
23558                   function getAndClearSevereErrors() {
23559                     return browser.manage().logs().get('browser').then(function(browserLog) {
23560                       return browserLog.filter(function(logEntry) {
23561                         return logEntry.level.value > webdriver.logging.Level.WARNING.value;
23562                       });
23563                     });
23564                   }
23565
23566                   function clearErrors() {
23567                     getAndClearSevereErrors();
23568                   }
23569
23570                   function expectNoErrors() {
23571                     getAndClearSevereErrors().then(function(filteredLog) {
23572                       expect(filteredLog.length).toEqual(0);
23573                       if (filteredLog.length) {
23574                         console.log('browser console errors: ' + util.inspect(filteredLog));
23575                       }
23576                     });
23577                   }
23578
23579                   function expectError(regex) {
23580                     getAndClearSevereErrors().then(function(filteredLog) {
23581                       var found = false;
23582                       filteredLog.forEach(function(log) {
23583                         if (log.message.match(regex)) {
23584                           found = true;
23585                         }
23586                       });
23587                       if (!found) {
23588                         throw new Error('expected an error that matches ' + regex);
23589                       }
23590                     });
23591                   }
23592
23593                   beforeEach(function() {
23594                     util = require('util');
23595                     webdriver = require('protractor/node_modules/selenium-webdriver');
23596                   });
23597
23598                   // For now, we only test on Chrome,
23599                   // as Safari does not load the page with Protractor's injected scripts,
23600                   // and Firefox webdriver always disables content security policy (#6358)
23601                   if (browser.params.browser !== 'chrome') {
23602                     return;
23603                   }
23604
23605                   it('should not report errors when the page is loaded', function() {
23606                     // clear errors so we are not dependent on previous tests
23607                     clearErrors();
23608                     // Need to reload the page as the page is already loaded when
23609                     // we come here
23610                     browser.driver.getCurrentUrl().then(function(url) {
23611                       browser.get(url);
23612                     });
23613                     expectNoErrors();
23614                   });
23615
23616                   it('should evaluate expressions', function() {
23617                     expect(counter.getText()).toEqual('0');
23618                     incBtn.click();
23619                     expect(counter.getText()).toEqual('1');
23620                     expectNoErrors();
23621                   });
23622
23623                   it('should throw and report an error when using "eval"', function() {
23624                     evilBtn.click();
23625                     expect(evilError.getText()).toMatch(/Content Security Policy/);
23626                     expectError(/Content Security Policy/);
23627                   });
23628                 </file>
23629               </example>
23630           */
23631
23632         // ngCsp is not implemented as a proper directive any more, because we need it be processed while we
23633         // bootstrap the system (before $parse is instantiated), for this reason we just have
23634         // the csp() fn that looks for the `ng-csp` attribute anywhere in the current doc
23635
23636         /**
23637          * @ngdoc directive
23638          * @name ngClick
23639          *
23640          * @description
23641          * The ngClick directive allows you to specify custom behavior when
23642          * an element is clicked.
23643          *
23644          * @element ANY
23645          * @priority 0
23646          * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
23647          * click. ({@link guide/expression#-event- Event object is available as `$event`})
23648          *
23649          * @example
23650            <example>
23651              <file name="index.html">
23652               <button ng-click="count = count + 1" ng-init="count=0">
23653                 Increment
23654               </button>
23655               <span>
23656                 count: {{count}}
23657               </span>
23658              </file>
23659              <file name="protractor.js" type="protractor">
23660                it('should check ng-click', function() {
23661                  expect(element(by.binding('count')).getText()).toMatch('0');
23662                  element(by.css('button')).click();
23663                  expect(element(by.binding('count')).getText()).toMatch('1');
23664                });
23665              </file>
23666            </example>
23667          */
23668         /*
23669          * A collection of directives that allows creation of custom event handlers that are defined as
23670          * angular expressions and are compiled and executed within the current scope.
23671          */
23672         var ngEventDirectives = {};
23673
23674         // For events that might fire synchronously during DOM manipulation
23675         // we need to execute their event handlers asynchronously using $evalAsync,
23676         // so that they are not executed in an inconsistent state.
23677         var forceAsyncEvents = {
23678           'blur': true,
23679           'focus': true
23680         };
23681         forEach(
23682           'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
23683           function(eventName) {
23684             var directiveName = directiveNormalize('ng-' + eventName);
23685             ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
23686               return {
23687                 restrict: 'A',
23688                 compile: function($element, attr) {
23689                   // We expose the powerful $event object on the scope that provides access to the Window,
23690                   // etc. that isn't protected by the fast paths in $parse.  We explicitly request better
23691                   // checks at the cost of speed since event handler expressions are not executed as
23692                   // frequently as regular change detection.
23693                   var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
23694                   return function ngEventHandler(scope, element) {
23695                     element.on(eventName, function(event) {
23696                       var callback = function() {
23697                         fn(scope, {$event:event});
23698                       };
23699                       if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
23700                         scope.$evalAsync(callback);
23701                       } else {
23702                         scope.$apply(callback);
23703                       }
23704                     });
23705                   };
23706                 }
23707               };
23708             }];
23709           }
23710         );
23711
23712         /**
23713          * @ngdoc directive
23714          * @name ngDblclick
23715          *
23716          * @description
23717          * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
23718          *
23719          * @element ANY
23720          * @priority 0
23721          * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
23722          * a dblclick. (The Event object is available as `$event`)
23723          *
23724          * @example
23725            <example>
23726              <file name="index.html">
23727               <button ng-dblclick="count = count + 1" ng-init="count=0">
23728                 Increment (on double click)
23729               </button>
23730               count: {{count}}
23731              </file>
23732            </example>
23733          */
23734
23735
23736         /**
23737          * @ngdoc directive
23738          * @name ngMousedown
23739          *
23740          * @description
23741          * The ngMousedown directive allows you to specify custom behavior on mousedown event.
23742          *
23743          * @element ANY
23744          * @priority 0
23745          * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
23746          * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
23747          *
23748          * @example
23749            <example>
23750              <file name="index.html">
23751               <button ng-mousedown="count = count + 1" ng-init="count=0">
23752                 Increment (on mouse down)
23753               </button>
23754               count: {{count}}
23755              </file>
23756            </example>
23757          */
23758
23759
23760         /**
23761          * @ngdoc directive
23762          * @name ngMouseup
23763          *
23764          * @description
23765          * Specify custom behavior on mouseup event.
23766          *
23767          * @element ANY
23768          * @priority 0
23769          * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
23770          * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
23771          *
23772          * @example
23773            <example>
23774              <file name="index.html">
23775               <button ng-mouseup="count = count + 1" ng-init="count=0">
23776                 Increment (on mouse up)
23777               </button>
23778               count: {{count}}
23779              </file>
23780            </example>
23781          */
23782
23783         /**
23784          * @ngdoc directive
23785          * @name ngMouseover
23786          *
23787          * @description
23788          * Specify custom behavior on mouseover event.
23789          *
23790          * @element ANY
23791          * @priority 0
23792          * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
23793          * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
23794          *
23795          * @example
23796            <example>
23797              <file name="index.html">
23798               <button ng-mouseover="count = count + 1" ng-init="count=0">
23799                 Increment (when mouse is over)
23800               </button>
23801               count: {{count}}
23802              </file>
23803            </example>
23804          */
23805
23806
23807         /**
23808          * @ngdoc directive
23809          * @name ngMouseenter
23810          *
23811          * @description
23812          * Specify custom behavior on mouseenter event.
23813          *
23814          * @element ANY
23815          * @priority 0
23816          * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
23817          * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
23818          *
23819          * @example
23820            <example>
23821              <file name="index.html">
23822               <button ng-mouseenter="count = count + 1" ng-init="count=0">
23823                 Increment (when mouse enters)
23824               </button>
23825               count: {{count}}
23826              </file>
23827            </example>
23828          */
23829
23830
23831         /**
23832          * @ngdoc directive
23833          * @name ngMouseleave
23834          *
23835          * @description
23836          * Specify custom behavior on mouseleave event.
23837          *
23838          * @element ANY
23839          * @priority 0
23840          * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
23841          * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
23842          *
23843          * @example
23844            <example>
23845              <file name="index.html">
23846               <button ng-mouseleave="count = count + 1" ng-init="count=0">
23847                 Increment (when mouse leaves)
23848               </button>
23849               count: {{count}}
23850              </file>
23851            </example>
23852          */
23853
23854
23855         /**
23856          * @ngdoc directive
23857          * @name ngMousemove
23858          *
23859          * @description
23860          * Specify custom behavior on mousemove event.
23861          *
23862          * @element ANY
23863          * @priority 0
23864          * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
23865          * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
23866          *
23867          * @example
23868            <example>
23869              <file name="index.html">
23870               <button ng-mousemove="count = count + 1" ng-init="count=0">
23871                 Increment (when mouse moves)
23872               </button>
23873               count: {{count}}
23874              </file>
23875            </example>
23876          */
23877
23878
23879         /**
23880          * @ngdoc directive
23881          * @name ngKeydown
23882          *
23883          * @description
23884          * Specify custom behavior on keydown event.
23885          *
23886          * @element ANY
23887          * @priority 0
23888          * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
23889          * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
23890          *
23891          * @example
23892            <example>
23893              <file name="index.html">
23894               <input ng-keydown="count = count + 1" ng-init="count=0">
23895               key down count: {{count}}
23896              </file>
23897            </example>
23898          */
23899
23900
23901         /**
23902          * @ngdoc directive
23903          * @name ngKeyup
23904          *
23905          * @description
23906          * Specify custom behavior on keyup event.
23907          *
23908          * @element ANY
23909          * @priority 0
23910          * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
23911          * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
23912          *
23913          * @example
23914            <example>
23915              <file name="index.html">
23916                <p>Typing in the input box below updates the key count</p>
23917                <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
23918
23919                <p>Typing in the input box below updates the keycode</p>
23920                <input ng-keyup="event=$event">
23921                <p>event keyCode: {{ event.keyCode }}</p>
23922                <p>event altKey: {{ event.altKey }}</p>
23923              </file>
23924            </example>
23925          */
23926
23927
23928         /**
23929          * @ngdoc directive
23930          * @name ngKeypress
23931          *
23932          * @description
23933          * Specify custom behavior on keypress event.
23934          *
23935          * @element ANY
23936          * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
23937          * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
23938          * and can be interrogated for keyCode, altKey, etc.)
23939          *
23940          * @example
23941            <example>
23942              <file name="index.html">
23943               <input ng-keypress="count = count + 1" ng-init="count=0">
23944               key press count: {{count}}
23945              </file>
23946            </example>
23947          */
23948
23949
23950         /**
23951          * @ngdoc directive
23952          * @name ngSubmit
23953          *
23954          * @description
23955          * Enables binding angular expressions to onsubmit events.
23956          *
23957          * Additionally it prevents the default action (which for form means sending the request to the
23958          * server and reloading the current page), but only if the form does not contain `action`,
23959          * `data-action`, or `x-action` attributes.
23960          *
23961          * <div class="alert alert-warning">
23962          * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
23963          * `ngSubmit` handlers together. See the
23964          * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
23965          * for a detailed discussion of when `ngSubmit` may be triggered.
23966          * </div>
23967          *
23968          * @element form
23969          * @priority 0
23970          * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
23971          * ({@link guide/expression#-event- Event object is available as `$event`})
23972          *
23973          * @example
23974            <example module="submitExample">
23975              <file name="index.html">
23976               <script>
23977                 angular.module('submitExample', [])
23978                   .controller('ExampleController', ['$scope', function($scope) {
23979                     $scope.list = [];
23980                     $scope.text = 'hello';
23981                     $scope.submit = function() {
23982                       if ($scope.text) {
23983                         $scope.list.push(this.text);
23984                         $scope.text = '';
23985                       }
23986                     };
23987                   }]);
23988               </script>
23989               <form ng-submit="submit()" ng-controller="ExampleController">
23990                 Enter text and hit enter:
23991                 <input type="text" ng-model="text" name="text" />
23992                 <input type="submit" id="submit" value="Submit" />
23993                 <pre>list={{list}}</pre>
23994               </form>
23995              </file>
23996              <file name="protractor.js" type="protractor">
23997                it('should check ng-submit', function() {
23998                  expect(element(by.binding('list')).getText()).toBe('list=[]');
23999                  element(by.css('#submit')).click();
24000                  expect(element(by.binding('list')).getText()).toContain('hello');
24001                  expect(element(by.model('text')).getAttribute('value')).toBe('');
24002                });
24003                it('should ignore empty strings', function() {
24004                  expect(element(by.binding('list')).getText()).toBe('list=[]');
24005                  element(by.css('#submit')).click();
24006                  element(by.css('#submit')).click();
24007                  expect(element(by.binding('list')).getText()).toContain('hello');
24008                 });
24009              </file>
24010            </example>
24011          */
24012
24013         /**
24014          * @ngdoc directive
24015          * @name ngFocus
24016          *
24017          * @description
24018          * Specify custom behavior on focus event.
24019          *
24020          * Note: As the `focus` event is executed synchronously when calling `input.focus()`
24021          * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
24022          * during an `$apply` to ensure a consistent state.
24023          *
24024          * @element window, input, select, textarea, a
24025          * @priority 0
24026          * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
24027          * focus. ({@link guide/expression#-event- Event object is available as `$event`})
24028          *
24029          * @example
24030          * See {@link ng.directive:ngClick ngClick}
24031          */
24032
24033         /**
24034          * @ngdoc directive
24035          * @name ngBlur
24036          *
24037          * @description
24038          * Specify custom behavior on blur event.
24039          *
24040          * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
24041          * an element has lost focus.
24042          *
24043          * Note: As the `blur` event is executed synchronously also during DOM manipulations
24044          * (e.g. removing a focussed input),
24045          * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
24046          * during an `$apply` to ensure a consistent state.
24047          *
24048          * @element window, input, select, textarea, a
24049          * @priority 0
24050          * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
24051          * blur. ({@link guide/expression#-event- Event object is available as `$event`})
24052          *
24053          * @example
24054          * See {@link ng.directive:ngClick ngClick}
24055          */
24056
24057         /**
24058          * @ngdoc directive
24059          * @name ngCopy
24060          *
24061          * @description
24062          * Specify custom behavior on copy event.
24063          *
24064          * @element window, input, select, textarea, a
24065          * @priority 0
24066          * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
24067          * copy. ({@link guide/expression#-event- Event object is available as `$event`})
24068          *
24069          * @example
24070            <example>
24071              <file name="index.html">
24072               <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
24073               copied: {{copied}}
24074              </file>
24075            </example>
24076          */
24077
24078         /**
24079          * @ngdoc directive
24080          * @name ngCut
24081          *
24082          * @description
24083          * Specify custom behavior on cut event.
24084          *
24085          * @element window, input, select, textarea, a
24086          * @priority 0
24087          * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
24088          * cut. ({@link guide/expression#-event- Event object is available as `$event`})
24089          *
24090          * @example
24091            <example>
24092              <file name="index.html">
24093               <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
24094               cut: {{cut}}
24095              </file>
24096            </example>
24097          */
24098
24099         /**
24100          * @ngdoc directive
24101          * @name ngPaste
24102          *
24103          * @description
24104          * Specify custom behavior on paste event.
24105          *
24106          * @element window, input, select, textarea, a
24107          * @priority 0
24108          * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
24109          * paste. ({@link guide/expression#-event- Event object is available as `$event`})
24110          *
24111          * @example
24112            <example>
24113              <file name="index.html">
24114               <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
24115               pasted: {{paste}}
24116              </file>
24117            </example>
24118          */
24119
24120         /**
24121          * @ngdoc directive
24122          * @name ngIf
24123          * @restrict A
24124          * @multiElement
24125          *
24126          * @description
24127          * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
24128          * {expression}. If the expression assigned to `ngIf` evaluates to a false
24129          * value then the element is removed from the DOM, otherwise a clone of the
24130          * element is reinserted into the DOM.
24131          *
24132          * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
24133          * element in the DOM rather than changing its visibility via the `display` css property.  A common
24134          * case when this difference is significant is when using css selectors that rely on an element's
24135          * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
24136          *
24137          * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
24138          * is created when the element is restored.  The scope created within `ngIf` inherits from
24139          * its parent scope using
24140          * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).
24141          * An important implication of this is if `ngModel` is used within `ngIf` to bind to
24142          * a javascript primitive defined in the parent scope. In this case any modifications made to the
24143          * variable within the child scope will override (hide) the value in the parent scope.
24144          *
24145          * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
24146          * is if an element's class attribute is directly modified after it's compiled, using something like
24147          * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
24148          * the added class will be lost because the original compiled state is used to regenerate the element.
24149          *
24150          * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
24151          * and `leave` effects.
24152          *
24153          * @animations
24154          * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container
24155          * leave - happens just before the `ngIf` contents are removed from the DOM
24156          *
24157          * @element ANY
24158          * @scope
24159          * @priority 600
24160          * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
24161          *     the element is removed from the DOM tree. If it is truthy a copy of the compiled
24162          *     element is added to the DOM tree.
24163          *
24164          * @example
24165           <example module="ngAnimate" deps="angular-animate.js" animations="true">
24166             <file name="index.html">
24167               <label>Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /></label><br/>
24168               Show when checked:
24169               <span ng-if="checked" class="animate-if">
24170                 This is removed when the checkbox is unchecked.
24171               </span>
24172             </file>
24173             <file name="animations.css">
24174               .animate-if {
24175                 background:white;
24176                 border:1px solid black;
24177                 padding:10px;
24178               }
24179
24180               .animate-if.ng-enter, .animate-if.ng-leave {
24181                 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
24182               }
24183
24184               .animate-if.ng-enter,
24185               .animate-if.ng-leave.ng-leave-active {
24186                 opacity:0;
24187               }
24188
24189               .animate-if.ng-leave,
24190               .animate-if.ng-enter.ng-enter-active {
24191                 opacity:1;
24192               }
24193             </file>
24194           </example>
24195          */
24196         var ngIfDirective = ['$animate', function($animate) {
24197           return {
24198             multiElement: true,
24199             transclude: 'element',
24200             priority: 600,
24201             terminal: true,
24202             restrict: 'A',
24203             $$tlb: true,
24204             link: function($scope, $element, $attr, ctrl, $transclude) {
24205                 var block, childScope, previousElements;
24206                 $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
24207
24208                   if (value) {
24209                     if (!childScope) {
24210                       $transclude(function(clone, newScope) {
24211                         childScope = newScope;
24212                         clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
24213                         // Note: We only need the first/last node of the cloned nodes.
24214                         // However, we need to keep the reference to the jqlite wrapper as it might be changed later
24215                         // by a directive with templateUrl when its template arrives.
24216                         block = {
24217                           clone: clone
24218                         };
24219                         $animate.enter(clone, $element.parent(), $element);
24220                       });
24221                     }
24222                   } else {
24223                     if (previousElements) {
24224                       previousElements.remove();
24225                       previousElements = null;
24226                     }
24227                     if (childScope) {
24228                       childScope.$destroy();
24229                       childScope = null;
24230                     }
24231                     if (block) {
24232                       previousElements = getBlockNodes(block.clone);
24233                       $animate.leave(previousElements).then(function() {
24234                         previousElements = null;
24235                       });
24236                       block = null;
24237                     }
24238                   }
24239                 });
24240             }
24241           };
24242         }];
24243
24244         /**
24245          * @ngdoc directive
24246          * @name ngInclude
24247          * @restrict ECA
24248          *
24249          * @description
24250          * Fetches, compiles and includes an external HTML fragment.
24251          *
24252          * By default, the template URL is restricted to the same domain and protocol as the
24253          * application document. This is done by calling {@link $sce#getTrustedResourceUrl
24254          * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
24255          * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
24256          * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
24257          * ng.$sce Strict Contextual Escaping}.
24258          *
24259          * In addition, the browser's
24260          * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
24261          * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
24262          * policy may further restrict whether the template is successfully loaded.
24263          * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
24264          * access on some browsers.
24265          *
24266          * @animations
24267          * enter - animation is used to bring new content into the browser.
24268          * leave - animation is used to animate existing content away.
24269          *
24270          * The enter and leave animation occur concurrently.
24271          *
24272          * @scope
24273          * @priority 400
24274          *
24275          * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
24276          *                 make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
24277          * @param {string=} onload Expression to evaluate when a new partial is loaded.
24278          *                  <div class="alert alert-warning">
24279          *                  **Note:** When using onload on SVG elements in IE11, the browser will try to call
24280          *                  a function with the name on the window element, which will usually throw a
24281          *                  "function is undefined" error. To fix this, you can instead use `data-onload` or a
24282          *                  different form that {@link guide/directive#normalization matches} `onload`.
24283          *                  </div>
24284            *
24285          * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
24286          *                  $anchorScroll} to scroll the viewport after the content is loaded.
24287          *
24288          *                  - If the attribute is not set, disable scrolling.
24289          *                  - If the attribute is set without value, enable scrolling.
24290          *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.
24291          *
24292          * @example
24293           <example module="includeExample" deps="angular-animate.js" animations="true">
24294             <file name="index.html">
24295              <div ng-controller="ExampleController">
24296                <select ng-model="template" ng-options="t.name for t in templates">
24297                 <option value="">(blank)</option>
24298                </select>
24299                url of the template: <code>{{template.url}}</code>
24300                <hr/>
24301                <div class="slide-animate-container">
24302                  <div class="slide-animate" ng-include="template.url"></div>
24303                </div>
24304              </div>
24305             </file>
24306             <file name="script.js">
24307               angular.module('includeExample', ['ngAnimate'])
24308                 .controller('ExampleController', ['$scope', function($scope) {
24309                   $scope.templates =
24310                     [ { name: 'template1.html', url: 'template1.html'},
24311                       { name: 'template2.html', url: 'template2.html'} ];
24312                   $scope.template = $scope.templates[0];
24313                 }]);
24314              </file>
24315             <file name="template1.html">
24316               Content of template1.html
24317             </file>
24318             <file name="template2.html">
24319               Content of template2.html
24320             </file>
24321             <file name="animations.css">
24322               .slide-animate-container {
24323                 position:relative;
24324                 background:white;
24325                 border:1px solid black;
24326                 height:40px;
24327                 overflow:hidden;
24328               }
24329
24330               .slide-animate {
24331                 padding:10px;
24332               }
24333
24334               .slide-animate.ng-enter, .slide-animate.ng-leave {
24335                 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
24336
24337                 position:absolute;
24338                 top:0;
24339                 left:0;
24340                 right:0;
24341                 bottom:0;
24342                 display:block;
24343                 padding:10px;
24344               }
24345
24346               .slide-animate.ng-enter {
24347                 top:-50px;
24348               }
24349               .slide-animate.ng-enter.ng-enter-active {
24350                 top:0;
24351               }
24352
24353               .slide-animate.ng-leave {
24354                 top:0;
24355               }
24356               .slide-animate.ng-leave.ng-leave-active {
24357                 top:50px;
24358               }
24359             </file>
24360             <file name="protractor.js" type="protractor">
24361               var templateSelect = element(by.model('template'));
24362               var includeElem = element(by.css('[ng-include]'));
24363
24364               it('should load template1.html', function() {
24365                 expect(includeElem.getText()).toMatch(/Content of template1.html/);
24366               });
24367
24368               it('should load template2.html', function() {
24369                 if (browser.params.browser == 'firefox') {
24370                   // Firefox can't handle using selects
24371                   // See https://github.com/angular/protractor/issues/480
24372                   return;
24373                 }
24374                 templateSelect.click();
24375                 templateSelect.all(by.css('option')).get(2).click();
24376                 expect(includeElem.getText()).toMatch(/Content of template2.html/);
24377               });
24378
24379               it('should change to blank', function() {
24380                 if (browser.params.browser == 'firefox') {
24381                   // Firefox can't handle using selects
24382                   return;
24383                 }
24384                 templateSelect.click();
24385                 templateSelect.all(by.css('option')).get(0).click();
24386                 expect(includeElem.isPresent()).toBe(false);
24387               });
24388             </file>
24389           </example>
24390          */
24391
24392
24393         /**
24394          * @ngdoc event
24395          * @name ngInclude#$includeContentRequested
24396          * @eventType emit on the scope ngInclude was declared in
24397          * @description
24398          * Emitted every time the ngInclude content is requested.
24399          *
24400          * @param {Object} angularEvent Synthetic event object.
24401          * @param {String} src URL of content to load.
24402          */
24403
24404
24405         /**
24406          * @ngdoc event
24407          * @name ngInclude#$includeContentLoaded
24408          * @eventType emit on the current ngInclude scope
24409          * @description
24410          * Emitted every time the ngInclude content is reloaded.
24411          *
24412          * @param {Object} angularEvent Synthetic event object.
24413          * @param {String} src URL of content to load.
24414          */
24415
24416
24417         /**
24418          * @ngdoc event
24419          * @name ngInclude#$includeContentError
24420          * @eventType emit on the scope ngInclude was declared in
24421          * @description
24422          * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)
24423          *
24424          * @param {Object} angularEvent Synthetic event object.
24425          * @param {String} src URL of content to load.
24426          */
24427         var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
24428                           function($templateRequest,   $anchorScroll,   $animate) {
24429           return {
24430             restrict: 'ECA',
24431             priority: 400,
24432             terminal: true,
24433             transclude: 'element',
24434             controller: angular.noop,
24435             compile: function(element, attr) {
24436               var srcExp = attr.ngInclude || attr.src,
24437                   onloadExp = attr.onload || '',
24438                   autoScrollExp = attr.autoscroll;
24439
24440               return function(scope, $element, $attr, ctrl, $transclude) {
24441                 var changeCounter = 0,
24442                     currentScope,
24443                     previousElement,
24444                     currentElement;
24445
24446                 var cleanupLastIncludeContent = function() {
24447                   if (previousElement) {
24448                     previousElement.remove();
24449                     previousElement = null;
24450                   }
24451                   if (currentScope) {
24452                     currentScope.$destroy();
24453                     currentScope = null;
24454                   }
24455                   if (currentElement) {
24456                     $animate.leave(currentElement).then(function() {
24457                       previousElement = null;
24458                     });
24459                     previousElement = currentElement;
24460                     currentElement = null;
24461                   }
24462                 };
24463
24464                 scope.$watch(srcExp, function ngIncludeWatchAction(src) {
24465                   var afterAnimation = function() {
24466                     if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
24467                       $anchorScroll();
24468                     }
24469                   };
24470                   var thisChangeId = ++changeCounter;
24471
24472                   if (src) {
24473                     //set the 2nd param to true to ignore the template request error so that the inner
24474                     //contents and scope can be cleaned up.
24475                     $templateRequest(src, true).then(function(response) {
24476                       if (thisChangeId !== changeCounter) return;
24477                       var newScope = scope.$new();
24478                       ctrl.template = response;
24479
24480                       // Note: This will also link all children of ng-include that were contained in the original
24481                       // html. If that content contains controllers, ... they could pollute/change the scope.
24482                       // However, using ng-include on an element with additional content does not make sense...
24483                       // Note: We can't remove them in the cloneAttchFn of $transclude as that
24484                       // function is called before linking the content, which would apply child
24485                       // directives to non existing elements.
24486                       var clone = $transclude(newScope, function(clone) {
24487                         cleanupLastIncludeContent();
24488                         $animate.enter(clone, null, $element).then(afterAnimation);
24489                       });
24490
24491                       currentScope = newScope;
24492                       currentElement = clone;
24493
24494                       currentScope.$emit('$includeContentLoaded', src);
24495                       scope.$eval(onloadExp);
24496                     }, function() {
24497                       if (thisChangeId === changeCounter) {
24498                         cleanupLastIncludeContent();
24499                         scope.$emit('$includeContentError', src);
24500                       }
24501                     });
24502                     scope.$emit('$includeContentRequested', src);
24503                   } else {
24504                     cleanupLastIncludeContent();
24505                     ctrl.template = null;
24506                   }
24507                 });
24508               };
24509             }
24510           };
24511         }];
24512
24513         // This directive is called during the $transclude call of the first `ngInclude` directive.
24514         // It will replace and compile the content of the element with the loaded template.
24515         // We need this directive so that the element content is already filled when
24516         // the link function of another directive on the same element as ngInclude
24517         // is called.
24518         var ngIncludeFillContentDirective = ['$compile',
24519           function($compile) {
24520             return {
24521               restrict: 'ECA',
24522               priority: -400,
24523               require: 'ngInclude',
24524               link: function(scope, $element, $attr, ctrl) {
24525                 if (/SVG/.test($element[0].toString())) {
24526                   // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
24527                   // support innerHTML, so detect this here and try to generate the contents
24528                   // specially.
24529                   $element.empty();
24530                   $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
24531                       function namespaceAdaptedClone(clone) {
24532                     $element.append(clone);
24533                   }, {futureParentElement: $element});
24534                   return;
24535                 }
24536
24537                 $element.html(ctrl.template);
24538                 $compile($element.contents())(scope);
24539               }
24540             };
24541           }];
24542
24543         /**
24544          * @ngdoc directive
24545          * @name ngInit
24546          * @restrict AC
24547          *
24548          * @description
24549          * The `ngInit` directive allows you to evaluate an expression in the
24550          * current scope.
24551          *
24552          * <div class="alert alert-danger">
24553          * This directive can be abused to add unnecessary amounts of logic into your templates.
24554          * There are only a few appropriate uses of `ngInit`, such as for aliasing special properties of
24555          * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below; and for injecting data via
24556          * server side scripting. Besides these few cases, you should use {@link guide/controller controllers}
24557          * rather than `ngInit` to initialize values on a scope.
24558          * </div>
24559          *
24560          * <div class="alert alert-warning">
24561          * **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make
24562          * sure you have parentheses to ensure correct operator precedence:
24563          * <pre class="prettyprint">
24564          * `<div ng-init="test1 = ($index | toString)"></div>`
24565          * </pre>
24566          * </div>
24567          *
24568          * @priority 450
24569          *
24570          * @element ANY
24571          * @param {expression} ngInit {@link guide/expression Expression} to eval.
24572          *
24573          * @example
24574            <example module="initExample">
24575              <file name="index.html">
24576            <script>
24577              angular.module('initExample', [])
24578                .controller('ExampleController', ['$scope', function($scope) {
24579                  $scope.list = [['a', 'b'], ['c', 'd']];
24580                }]);
24581            </script>
24582            <div ng-controller="ExampleController">
24583              <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
24584                <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
24585                   <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
24586                </div>
24587              </div>
24588            </div>
24589              </file>
24590              <file name="protractor.js" type="protractor">
24591                it('should alias index positions', function() {
24592                  var elements = element.all(by.css('.example-init'));
24593                  expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
24594                  expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
24595                  expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
24596                  expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
24597                });
24598              </file>
24599            </example>
24600          */
24601         var ngInitDirective = ngDirective({
24602           priority: 450,
24603           compile: function() {
24604             return {
24605               pre: function(scope, element, attrs) {
24606                 scope.$eval(attrs.ngInit);
24607               }
24608             };
24609           }
24610         });
24611
24612         /**
24613          * @ngdoc directive
24614          * @name ngList
24615          *
24616          * @description
24617          * Text input that converts between a delimited string and an array of strings. The default
24618          * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom
24619          * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`.
24620          *
24621          * The behaviour of the directive is affected by the use of the `ngTrim` attribute.
24622          * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each
24623          *   list item is respected. This implies that the user of the directive is responsible for
24624          *   dealing with whitespace but also allows you to use whitespace as a delimiter, such as a
24625          *   tab or newline character.
24626          * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected
24627          *   when joining the list items back together) and whitespace around each list item is stripped
24628          *   before it is added to the model.
24629          *
24630          * ### Example with Validation
24631          *
24632          * <example name="ngList-directive" module="listExample">
24633          *   <file name="app.js">
24634          *      angular.module('listExample', [])
24635          *        .controller('ExampleController', ['$scope', function($scope) {
24636          *          $scope.names = ['morpheus', 'neo', 'trinity'];
24637          *        }]);
24638          *   </file>
24639          *   <file name="index.html">
24640          *    <form name="myForm" ng-controller="ExampleController">
24641          *      <label>List: <input name="namesInput" ng-model="names" ng-list required></label>
24642          *      <span role="alert">
24643          *        <span class="error" ng-show="myForm.namesInput.$error.required">
24644          *        Required!</span>
24645          *      </span>
24646          *      <br>
24647          *      <tt>names = {{names}}</tt><br/>
24648          *      <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
24649          *      <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
24650          *      <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
24651          *      <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
24652          *     </form>
24653          *   </file>
24654          *   <file name="protractor.js" type="protractor">
24655          *     var listInput = element(by.model('names'));
24656          *     var names = element(by.exactBinding('names'));
24657          *     var valid = element(by.binding('myForm.namesInput.$valid'));
24658          *     var error = element(by.css('span.error'));
24659          *
24660          *     it('should initialize to model', function() {
24661          *       expect(names.getText()).toContain('["morpheus","neo","trinity"]');
24662          *       expect(valid.getText()).toContain('true');
24663          *       expect(error.getCssValue('display')).toBe('none');
24664          *     });
24665          *
24666          *     it('should be invalid if empty', function() {
24667          *       listInput.clear();
24668          *       listInput.sendKeys('');
24669          *
24670          *       expect(names.getText()).toContain('');
24671          *       expect(valid.getText()).toContain('false');
24672          *       expect(error.getCssValue('display')).not.toBe('none');
24673          *     });
24674          *   </file>
24675          * </example>
24676          *
24677          * ### Example - splitting on newline
24678          * <example name="ngList-directive-newlines">
24679          *   <file name="index.html">
24680          *    <textarea ng-model="list" ng-list="&#10;" ng-trim="false"></textarea>
24681          *    <pre>{{ list | json }}</pre>
24682          *   </file>
24683          *   <file name="protractor.js" type="protractor">
24684          *     it("should split the text by newlines", function() {
24685          *       var listInput = element(by.model('list'));
24686          *       var output = element(by.binding('list | json'));
24687          *       listInput.sendKeys('abc\ndef\nghi');
24688          *       expect(output.getText()).toContain('[\n  "abc",\n  "def",\n  "ghi"\n]');
24689          *     });
24690          *   </file>
24691          * </example>
24692          *
24693          * @element input
24694          * @param {string=} ngList optional delimiter that should be used to split the value.
24695          */
24696         var ngListDirective = function() {
24697           return {
24698             restrict: 'A',
24699             priority: 100,
24700             require: 'ngModel',
24701             link: function(scope, element, attr, ctrl) {
24702               // We want to control whitespace trimming so we use this convoluted approach
24703               // to access the ngList attribute, which doesn't pre-trim the attribute
24704               var ngList = element.attr(attr.$attr.ngList) || ', ';
24705               var trimValues = attr.ngTrim !== 'false';
24706               var separator = trimValues ? trim(ngList) : ngList;
24707
24708               var parse = function(viewValue) {
24709                 // If the viewValue is invalid (say required but empty) it will be `undefined`
24710                 if (isUndefined(viewValue)) return;
24711
24712                 var list = [];
24713
24714                 if (viewValue) {
24715                   forEach(viewValue.split(separator), function(value) {
24716                     if (value) list.push(trimValues ? trim(value) : value);
24717                   });
24718                 }
24719
24720                 return list;
24721               };
24722
24723               ctrl.$parsers.push(parse);
24724               ctrl.$formatters.push(function(value) {
24725                 if (isArray(value)) {
24726                   return value.join(ngList);
24727                 }
24728
24729                 return undefined;
24730               });
24731
24732               // Override the standard $isEmpty because an empty array means the input is empty.
24733               ctrl.$isEmpty = function(value) {
24734                 return !value || !value.length;
24735               };
24736             }
24737           };
24738         };
24739
24740         /* global VALID_CLASS: true,
24741           INVALID_CLASS: true,
24742           PRISTINE_CLASS: true,
24743           DIRTY_CLASS: true,
24744           UNTOUCHED_CLASS: true,
24745           TOUCHED_CLASS: true,
24746         */
24747
24748         var VALID_CLASS = 'ng-valid',
24749             INVALID_CLASS = 'ng-invalid',
24750             PRISTINE_CLASS = 'ng-pristine',
24751             DIRTY_CLASS = 'ng-dirty',
24752             UNTOUCHED_CLASS = 'ng-untouched',
24753             TOUCHED_CLASS = 'ng-touched',
24754             PENDING_CLASS = 'ng-pending';
24755
24756         var ngModelMinErr = minErr('ngModel');
24757
24758         /**
24759          * @ngdoc type
24760          * @name ngModel.NgModelController
24761          *
24762          * @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a
24763          * String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue
24764          * is set.
24765          * @property {*} $modelValue The value in the model that the control is bound to.
24766          * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
24767                the control reads value from the DOM. The functions are called in array order, each passing
24768                its return value through to the next. The last return value is forwarded to the
24769                {@link ngModel.NgModelController#$validators `$validators`} collection.
24770
24771         Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
24772         `$viewValue`}.
24773
24774         Returning `undefined` from a parser means a parse error occurred. In that case,
24775         no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
24776         will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
24777         is set to `true`. The parse error is stored in `ngModel.$error.parse`.
24778
24779          *
24780          * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
24781                the model value changes. The functions are called in reverse array order, each passing the value through to the
24782                next. The last return value is used as the actual DOM value.
24783                Used to format / convert values for display in the control.
24784          * ```js
24785          * function formatter(value) {
24786          *   if (value) {
24787          *     return value.toUpperCase();
24788          *   }
24789          * }
24790          * ngModel.$formatters.push(formatter);
24791          * ```
24792          *
24793          * @property {Object.<string, function>} $validators A collection of validators that are applied
24794          *      whenever the model value changes. The key value within the object refers to the name of the
24795          *      validator while the function refers to the validation operation. The validation operation is
24796          *      provided with the model value as an argument and must return a true or false value depending
24797          *      on the response of that validation.
24798          *
24799          * ```js
24800          * ngModel.$validators.validCharacters = function(modelValue, viewValue) {
24801          *   var value = modelValue || viewValue;
24802          *   return /[0-9]+/.test(value) &&
24803          *          /[a-z]+/.test(value) &&
24804          *          /[A-Z]+/.test(value) &&
24805          *          /\W+/.test(value);
24806          * };
24807          * ```
24808          *
24809          * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
24810          *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
24811          *      is expected to return a promise when it is run during the model validation process. Once the promise
24812          *      is delivered then the validation status will be set to true when fulfilled and false when rejected.
24813          *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model
24814          *      value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
24815          *      is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
24816          *      will only run once all synchronous validators have passed.
24817          *
24818          * Please note that if $http is used then it is important that the server returns a success HTTP response code
24819          * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
24820          *
24821          * ```js
24822          * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
24823          *   var value = modelValue || viewValue;
24824          *
24825          *   // Lookup user by username
24826          *   return $http.get('/api/users/' + value).
24827          *      then(function resolved() {
24828          *        //username exists, this means validation fails
24829          *        return $q.reject('exists');
24830          *      }, function rejected() {
24831          *        //username does not exist, therefore this validation passes
24832          *        return true;
24833          *      });
24834          * };
24835          * ```
24836          *
24837          * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
24838          *     view value has changed. It is called with no arguments, and its return value is ignored.
24839          *     This can be used in place of additional $watches against the model value.
24840          *
24841          * @property {Object} $error An object hash with all failing validator ids as keys.
24842          * @property {Object} $pending An object hash with all pending validator ids as keys.
24843          *
24844          * @property {boolean} $untouched True if control has not lost focus yet.
24845          * @property {boolean} $touched True if control has lost focus.
24846          * @property {boolean} $pristine True if user has not interacted with the control yet.
24847          * @property {boolean} $dirty True if user has already interacted with the control.
24848          * @property {boolean} $valid True if there is no error.
24849          * @property {boolean} $invalid True if at least one error on the control.
24850          * @property {string} $name The name attribute of the control.
24851          *
24852          * @description
24853          *
24854          * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.
24855          * The controller contains services for data-binding, validation, CSS updates, and value formatting
24856          * and parsing. It purposefully does not contain any logic which deals with DOM rendering or
24857          * listening to DOM events.
24858          * Such DOM related logic should be provided by other directives which make use of
24859          * `NgModelController` for data-binding to control elements.
24860          * Angular provides this DOM logic for most {@link input `input`} elements.
24861          * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example
24862          * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.
24863          *
24864          * @example
24865          * ### Custom Control Example
24866          * This example shows how to use `NgModelController` with a custom control to achieve
24867          * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
24868          * collaborate together to achieve the desired result.
24869          *
24870          * `contenteditable` is an HTML5 attribute, which tells the browser to let the element
24871          * contents be edited in place by the user.
24872          *
24873          * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
24874          * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
24875          * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
24876          * that content using the `$sce` service.
24877          *
24878          * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
24879             <file name="style.css">
24880               [contenteditable] {
24881                 border: 1px solid black;
24882                 background-color: white;
24883                 min-height: 20px;
24884               }
24885
24886               .ng-invalid {
24887                 border: 1px solid red;
24888               }
24889
24890             </file>
24891             <file name="script.js">
24892               angular.module('customControl', ['ngSanitize']).
24893                 directive('contenteditable', ['$sce', function($sce) {
24894                   return {
24895                     restrict: 'A', // only activate on element attribute
24896                     require: '?ngModel', // get a hold of NgModelController
24897                     link: function(scope, element, attrs, ngModel) {
24898                       if (!ngModel) return; // do nothing if no ng-model
24899
24900                       // Specify how UI should be updated
24901                       ngModel.$render = function() {
24902                         element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
24903                       };
24904
24905                       // Listen for change events to enable binding
24906                       element.on('blur keyup change', function() {
24907                         scope.$evalAsync(read);
24908                       });
24909                       read(); // initialize
24910
24911                       // Write data to the model
24912                       function read() {
24913                         var html = element.html();
24914                         // When we clear the content editable the browser leaves a <br> behind
24915                         // If strip-br attribute is provided then we strip this out
24916                         if ( attrs.stripBr && html == '<br>' ) {
24917                           html = '';
24918                         }
24919                         ngModel.$setViewValue(html);
24920                       }
24921                     }
24922                   };
24923                 }]);
24924             </file>
24925             <file name="index.html">
24926               <form name="myForm">
24927                <div contenteditable
24928                     name="myWidget" ng-model="userContent"
24929                     strip-br="true"
24930                     required>Change me!</div>
24931                 <span ng-show="myForm.myWidget.$error.required">Required!</span>
24932                <hr>
24933                <textarea ng-model="userContent" aria-label="Dynamic textarea"></textarea>
24934               </form>
24935             </file>
24936             <file name="protractor.js" type="protractor">
24937             it('should data-bind and become invalid', function() {
24938               if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
24939                 // SafariDriver can't handle contenteditable
24940                 // and Firefox driver can't clear contenteditables very well
24941                 return;
24942               }
24943               var contentEditable = element(by.css('[contenteditable]'));
24944               var content = 'Change me!';
24945
24946               expect(contentEditable.getText()).toEqual(content);
24947
24948               contentEditable.clear();
24949               contentEditable.sendKeys(protractor.Key.BACK_SPACE);
24950               expect(contentEditable.getText()).toEqual('');
24951               expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
24952             });
24953             </file>
24954          * </example>
24955          *
24956          *
24957          */
24958         var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
24959             function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
24960           this.$viewValue = Number.NaN;
24961           this.$modelValue = Number.NaN;
24962           this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
24963           this.$validators = {};
24964           this.$asyncValidators = {};
24965           this.$parsers = [];
24966           this.$formatters = [];
24967           this.$viewChangeListeners = [];
24968           this.$untouched = true;
24969           this.$touched = false;
24970           this.$pristine = true;
24971           this.$dirty = false;
24972           this.$valid = true;
24973           this.$invalid = false;
24974           this.$error = {}; // keep invalid keys here
24975           this.$$success = {}; // keep valid keys here
24976           this.$pending = undefined; // keep pending keys here
24977           this.$name = $interpolate($attr.name || '', false)($scope);
24978           this.$$parentForm = nullFormCtrl;
24979
24980           var parsedNgModel = $parse($attr.ngModel),
24981               parsedNgModelAssign = parsedNgModel.assign,
24982               ngModelGet = parsedNgModel,
24983               ngModelSet = parsedNgModelAssign,
24984               pendingDebounce = null,
24985               parserValid,
24986               ctrl = this;
24987
24988           this.$$setOptions = function(options) {
24989             ctrl.$options = options;
24990             if (options && options.getterSetter) {
24991               var invokeModelGetter = $parse($attr.ngModel + '()'),
24992                   invokeModelSetter = $parse($attr.ngModel + '($$$p)');
24993
24994               ngModelGet = function($scope) {
24995                 var modelValue = parsedNgModel($scope);
24996                 if (isFunction(modelValue)) {
24997                   modelValue = invokeModelGetter($scope);
24998                 }
24999                 return modelValue;
25000               };
25001               ngModelSet = function($scope, newValue) {
25002                 if (isFunction(parsedNgModel($scope))) {
25003                   invokeModelSetter($scope, {$$$p: ctrl.$modelValue});
25004                 } else {
25005                   parsedNgModelAssign($scope, ctrl.$modelValue);
25006                 }
25007               };
25008             } else if (!parsedNgModel.assign) {
25009               throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
25010                   $attr.ngModel, startingTag($element));
25011             }
25012           };
25013
25014           /**
25015            * @ngdoc method
25016            * @name ngModel.NgModelController#$render
25017            *
25018            * @description
25019            * Called when the view needs to be updated. It is expected that the user of the ng-model
25020            * directive will implement this method.
25021            *
25022            * The `$render()` method is invoked in the following situations:
25023            *
25024            * * `$rollbackViewValue()` is called.  If we are rolling back the view value to the last
25025            *   committed value then `$render()` is called to update the input control.
25026            * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
25027            *   the `$viewValue` are different from last time.
25028            *
25029            * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
25030            * `$modelValue` and `$viewValue` are actually different from their previous value. If `$modelValue`
25031            * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
25032            * invoked if you only change a property on the objects.
25033            */
25034           this.$render = noop;
25035
25036           /**
25037            * @ngdoc method
25038            * @name ngModel.NgModelController#$isEmpty
25039            *
25040            * @description
25041            * This is called when we need to determine if the value of an input is empty.
25042            *
25043            * For instance, the required directive does this to work out if the input has data or not.
25044            *
25045            * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
25046            *
25047            * You can override this for input directives whose concept of being empty is different from the
25048            * default. The `checkboxInputType` directive does this because in its case a value of `false`
25049            * implies empty.
25050            *
25051            * @param {*} value The value of the input to check for emptiness.
25052            * @returns {boolean} True if `value` is "empty".
25053            */
25054           this.$isEmpty = function(value) {
25055             return isUndefined(value) || value === '' || value === null || value !== value;
25056           };
25057
25058           var currentValidationRunId = 0;
25059
25060           /**
25061            * @ngdoc method
25062            * @name ngModel.NgModelController#$setValidity
25063            *
25064            * @description
25065            * Change the validity state, and notify the form.
25066            *
25067            * This method can be called within $parsers/$formatters or a custom validation implementation.
25068            * However, in most cases it should be sufficient to use the `ngModel.$validators` and
25069            * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
25070            *
25071            * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
25072            *        to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
25073            *        (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
25074            *        The `validationErrorKey` should be in camelCase and will get converted into dash-case
25075            *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
25076            *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .
25077            * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
25078            *                          or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
25079            *                          Skipped is used by Angular when validators do not run because of parse errors and
25080            *                          when `$asyncValidators` do not run because any of the `$validators` failed.
25081            */
25082           addSetValidityMethod({
25083             ctrl: this,
25084             $element: $element,
25085             set: function(object, property) {
25086               object[property] = true;
25087             },
25088             unset: function(object, property) {
25089               delete object[property];
25090             },
25091             $animate: $animate
25092           });
25093
25094           /**
25095            * @ngdoc method
25096            * @name ngModel.NgModelController#$setPristine
25097            *
25098            * @description
25099            * Sets the control to its pristine state.
25100            *
25101            * This method can be called to remove the `ng-dirty` class and set the control to its pristine
25102            * state (`ng-pristine` class). A model is considered to be pristine when the control
25103            * has not been changed from when first compiled.
25104            */
25105           this.$setPristine = function() {
25106             ctrl.$dirty = false;
25107             ctrl.$pristine = true;
25108             $animate.removeClass($element, DIRTY_CLASS);
25109             $animate.addClass($element, PRISTINE_CLASS);
25110           };
25111
25112           /**
25113            * @ngdoc method
25114            * @name ngModel.NgModelController#$setDirty
25115            *
25116            * @description
25117            * Sets the control to its dirty state.
25118            *
25119            * This method can be called to remove the `ng-pristine` class and set the control to its dirty
25120            * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed
25121            * from when first compiled.
25122            */
25123           this.$setDirty = function() {
25124             ctrl.$dirty = true;
25125             ctrl.$pristine = false;
25126             $animate.removeClass($element, PRISTINE_CLASS);
25127             $animate.addClass($element, DIRTY_CLASS);
25128             ctrl.$$parentForm.$setDirty();
25129           };
25130
25131           /**
25132            * @ngdoc method
25133            * @name ngModel.NgModelController#$setUntouched
25134            *
25135            * @description
25136            * Sets the control to its untouched state.
25137            *
25138            * This method can be called to remove the `ng-touched` class and set the control to its
25139            * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched
25140            * by default, however this function can be used to restore that state if the model has
25141            * already been touched by the user.
25142            */
25143           this.$setUntouched = function() {
25144             ctrl.$touched = false;
25145             ctrl.$untouched = true;
25146             $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);
25147           };
25148
25149           /**
25150            * @ngdoc method
25151            * @name ngModel.NgModelController#$setTouched
25152            *
25153            * @description
25154            * Sets the control to its touched state.
25155            *
25156            * This method can be called to remove the `ng-untouched` class and set the control to its
25157            * touched state (`ng-touched` class). A model is considered to be touched when the user has
25158            * first focused the control element and then shifted focus away from the control (blur event).
25159            */
25160           this.$setTouched = function() {
25161             ctrl.$touched = true;
25162             ctrl.$untouched = false;
25163             $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
25164           };
25165
25166           /**
25167            * @ngdoc method
25168            * @name ngModel.NgModelController#$rollbackViewValue
25169            *
25170            * @description
25171            * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,
25172            * which may be caused by a pending debounced event or because the input is waiting for a some
25173            * future event.
25174            *
25175            * If you have an input that uses `ng-model-options` to set up debounced events or events such
25176            * as blur you can have a situation where there is a period when the `$viewValue`
25177            * is out of synch with the ngModel's `$modelValue`.
25178            *
25179            * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`
25180            * programmatically before these debounced/future events have resolved/occurred, because Angular's
25181            * dirty checking mechanism is not able to tell whether the model has actually changed or not.
25182            *
25183            * The `$rollbackViewValue()` method should be called before programmatically changing the model of an
25184            * input which may have such events pending. This is important in order to make sure that the
25185            * input field will be updated with the new model value and any pending operations are cancelled.
25186            *
25187            * <example name="ng-model-cancel-update" module="cancel-update-example">
25188            *   <file name="app.js">
25189            *     angular.module('cancel-update-example', [])
25190            *
25191            *     .controller('CancelUpdateController', ['$scope', function($scope) {
25192            *       $scope.resetWithCancel = function(e) {
25193            *         if (e.keyCode == 27) {
25194            *           $scope.myForm.myInput1.$rollbackViewValue();
25195            *           $scope.myValue = '';
25196            *         }
25197            *       };
25198            *       $scope.resetWithoutCancel = function(e) {
25199            *         if (e.keyCode == 27) {
25200            *           $scope.myValue = '';
25201            *         }
25202            *       };
25203            *     }]);
25204            *   </file>
25205            *   <file name="index.html">
25206            *     <div ng-controller="CancelUpdateController">
25207            *       <p>Try typing something in each input.  See that the model only updates when you
25208            *          blur off the input.
25209            *        </p>
25210            *        <p>Now see what happens if you start typing then press the Escape key</p>
25211            *
25212            *       <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
25213            *         <p id="inputDescription1">With $rollbackViewValue()</p>
25214            *         <input name="myInput1" aria-describedby="inputDescription1" ng-model="myValue"
25215            *                ng-keydown="resetWithCancel($event)"><br/>
25216            *         myValue: "{{ myValue }}"
25217            *
25218            *         <p id="inputDescription2">Without $rollbackViewValue()</p>
25219            *         <input name="myInput2" aria-describedby="inputDescription2" ng-model="myValue"
25220            *                ng-keydown="resetWithoutCancel($event)"><br/>
25221            *         myValue: "{{ myValue }}"
25222            *       </form>
25223            *     </div>
25224            *   </file>
25225            * </example>
25226            */
25227           this.$rollbackViewValue = function() {
25228             $timeout.cancel(pendingDebounce);
25229             ctrl.$viewValue = ctrl.$$lastCommittedViewValue;
25230             ctrl.$render();
25231           };
25232
25233           /**
25234            * @ngdoc method
25235            * @name ngModel.NgModelController#$validate
25236            *
25237            * @description
25238            * Runs each of the registered validators (first synchronous validators and then
25239            * asynchronous validators).
25240            * If the validity changes to invalid, the model will be set to `undefined`,
25241            * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
25242            * If the validity changes to valid, it will set the model to the last available valid
25243            * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
25244            */
25245           this.$validate = function() {
25246             // ignore $validate before model is initialized
25247             if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
25248               return;
25249             }
25250
25251             var viewValue = ctrl.$$lastCommittedViewValue;
25252             // Note: we use the $$rawModelValue as $modelValue might have been
25253             // set to undefined during a view -> model update that found validation
25254             // errors. We can't parse the view here, since that could change
25255             // the model although neither viewValue nor the model on the scope changed
25256             var modelValue = ctrl.$$rawModelValue;
25257
25258             var prevValid = ctrl.$valid;
25259             var prevModelValue = ctrl.$modelValue;
25260
25261             var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
25262
25263             ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
25264               // If there was no change in validity, don't update the model
25265               // This prevents changing an invalid modelValue to undefined
25266               if (!allowInvalid && prevValid !== allValid) {
25267                 // Note: Don't check ctrl.$valid here, as we could have
25268                 // external validators (e.g. calculated on the server),
25269                 // that just call $setValidity and need the model value
25270                 // to calculate their validity.
25271                 ctrl.$modelValue = allValid ? modelValue : undefined;
25272
25273                 if (ctrl.$modelValue !== prevModelValue) {
25274                   ctrl.$$writeModelToScope();
25275                 }
25276               }
25277             });
25278
25279           };
25280
25281           this.$$runValidators = function(modelValue, viewValue, doneCallback) {
25282             currentValidationRunId++;
25283             var localValidationRunId = currentValidationRunId;
25284
25285             // check parser error
25286             if (!processParseErrors()) {
25287               validationDone(false);
25288               return;
25289             }
25290             if (!processSyncValidators()) {
25291               validationDone(false);
25292               return;
25293             }
25294             processAsyncValidators();
25295
25296             function processParseErrors() {
25297               var errorKey = ctrl.$$parserName || 'parse';
25298               if (isUndefined(parserValid)) {
25299                 setValidity(errorKey, null);
25300               } else {
25301                 if (!parserValid) {
25302                   forEach(ctrl.$validators, function(v, name) {
25303                     setValidity(name, null);
25304                   });
25305                   forEach(ctrl.$asyncValidators, function(v, name) {
25306                     setValidity(name, null);
25307                   });
25308                 }
25309                 // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
25310                 setValidity(errorKey, parserValid);
25311                 return parserValid;
25312               }
25313               return true;
25314             }
25315
25316             function processSyncValidators() {
25317               var syncValidatorsValid = true;
25318               forEach(ctrl.$validators, function(validator, name) {
25319                 var result = validator(modelValue, viewValue);
25320                 syncValidatorsValid = syncValidatorsValid && result;
25321                 setValidity(name, result);
25322               });
25323               if (!syncValidatorsValid) {
25324                 forEach(ctrl.$asyncValidators, function(v, name) {
25325                   setValidity(name, null);
25326                 });
25327                 return false;
25328               }
25329               return true;
25330             }
25331
25332             function processAsyncValidators() {
25333               var validatorPromises = [];
25334               var allValid = true;
25335               forEach(ctrl.$asyncValidators, function(validator, name) {
25336                 var promise = validator(modelValue, viewValue);
25337                 if (!isPromiseLike(promise)) {
25338                   throw ngModelMinErr("$asyncValidators",
25339                     "Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
25340                 }
25341                 setValidity(name, undefined);
25342                 validatorPromises.push(promise.then(function() {
25343                   setValidity(name, true);
25344                 }, function(error) {
25345                   allValid = false;
25346                   setValidity(name, false);
25347                 }));
25348               });
25349               if (!validatorPromises.length) {
25350                 validationDone(true);
25351               } else {
25352                 $q.all(validatorPromises).then(function() {
25353                   validationDone(allValid);
25354                 }, noop);
25355               }
25356             }
25357
25358             function setValidity(name, isValid) {
25359               if (localValidationRunId === currentValidationRunId) {
25360                 ctrl.$setValidity(name, isValid);
25361               }
25362             }
25363
25364             function validationDone(allValid) {
25365               if (localValidationRunId === currentValidationRunId) {
25366
25367                 doneCallback(allValid);
25368               }
25369             }
25370           };
25371
25372           /**
25373            * @ngdoc method
25374            * @name ngModel.NgModelController#$commitViewValue
25375            *
25376            * @description
25377            * Commit a pending update to the `$modelValue`.
25378            *
25379            * Updates may be pending by a debounced event or because the input is waiting for a some future
25380            * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
25381            * usually handles calling this in response to input events.
25382            */
25383           this.$commitViewValue = function() {
25384             var viewValue = ctrl.$viewValue;
25385
25386             $timeout.cancel(pendingDebounce);
25387
25388             // If the view value has not changed then we should just exit, except in the case where there is
25389             // a native validator on the element. In this case the validation state may have changed even though
25390             // the viewValue has stayed empty.
25391             if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
25392               return;
25393             }
25394             ctrl.$$lastCommittedViewValue = viewValue;
25395
25396             // change to dirty
25397             if (ctrl.$pristine) {
25398               this.$setDirty();
25399             }
25400             this.$$parseAndValidate();
25401           };
25402
25403           this.$$parseAndValidate = function() {
25404             var viewValue = ctrl.$$lastCommittedViewValue;
25405             var modelValue = viewValue;
25406             parserValid = isUndefined(modelValue) ? undefined : true;
25407
25408             if (parserValid) {
25409               for (var i = 0; i < ctrl.$parsers.length; i++) {
25410                 modelValue = ctrl.$parsers[i](modelValue);
25411                 if (isUndefined(modelValue)) {
25412                   parserValid = false;
25413                   break;
25414                 }
25415               }
25416             }
25417             if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
25418               // ctrl.$modelValue has not been touched yet...
25419               ctrl.$modelValue = ngModelGet($scope);
25420             }
25421             var prevModelValue = ctrl.$modelValue;
25422             var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
25423             ctrl.$$rawModelValue = modelValue;
25424
25425             if (allowInvalid) {
25426               ctrl.$modelValue = modelValue;
25427               writeToModelIfNeeded();
25428             }
25429
25430             // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
25431             // This can happen if e.g. $setViewValue is called from inside a parser
25432             ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
25433               if (!allowInvalid) {
25434                 // Note: Don't check ctrl.$valid here, as we could have
25435                 // external validators (e.g. calculated on the server),
25436                 // that just call $setValidity and need the model value
25437                 // to calculate their validity.
25438                 ctrl.$modelValue = allValid ? modelValue : undefined;
25439                 writeToModelIfNeeded();
25440               }
25441             });
25442
25443             function writeToModelIfNeeded() {
25444               if (ctrl.$modelValue !== prevModelValue) {
25445                 ctrl.$$writeModelToScope();
25446               }
25447             }
25448           };
25449
25450           this.$$writeModelToScope = function() {
25451             ngModelSet($scope, ctrl.$modelValue);
25452             forEach(ctrl.$viewChangeListeners, function(listener) {
25453               try {
25454                 listener();
25455               } catch (e) {
25456                 $exceptionHandler(e);
25457               }
25458             });
25459           };
25460
25461           /**
25462            * @ngdoc method
25463            * @name ngModel.NgModelController#$setViewValue
25464            *
25465            * @description
25466            * Update the view value.
25467            *
25468            * This method should be called when a control wants to change the view value; typically,
25469            * this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
25470            * directive calls it when the value of the input changes and {@link ng.directive:select select}
25471            * calls it when an option is selected.
25472            *
25473            * When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
25474            * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
25475            * value sent directly for processing, finally to be applied to `$modelValue` and then the
25476            * **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
25477            * in the `$viewChangeListeners` list, are called.
25478            *
25479            * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
25480            * and the `default` trigger is not listed, all those actions will remain pending until one of the
25481            * `updateOn` events is triggered on the DOM element.
25482            * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
25483            * directive is used with a custom debounce for this particular event.
25484            * Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
25485            * is specified, once the timer runs out.
25486            *
25487            * When used with standard inputs, the view value will always be a string (which is in some cases
25488            * parsed into another type, such as a `Date` object for `input[date]`.)
25489            * However, custom controls might also pass objects to this method. In this case, we should make
25490            * a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
25491            * perform a deep watch of objects, it only looks for a change of identity. If you only change
25492            * the property of the object then ngModel will not realise that the object has changed and
25493            * will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
25494            * not change properties of the copy once it has been passed to `$setViewValue`.
25495            * Otherwise you may cause the model value on the scope to change incorrectly.
25496            *
25497            * <div class="alert alert-info">
25498            * In any case, the value passed to the method should always reflect the current value
25499            * of the control. For example, if you are calling `$setViewValue` for an input element,
25500            * you should pass the input DOM value. Otherwise, the control and the scope model become
25501            * out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
25502            * the control's DOM value in any way. If we want to change the control's DOM value
25503            * programmatically, we should update the `ngModel` scope expression. Its new value will be
25504            * picked up by the model controller, which will run it through the `$formatters`, `$render` it
25505            * to update the DOM, and finally call `$validate` on it.
25506            * </div>
25507            *
25508            * @param {*} value value from the view.
25509            * @param {string} trigger Event that triggered the update.
25510            */
25511           this.$setViewValue = function(value, trigger) {
25512             ctrl.$viewValue = value;
25513             if (!ctrl.$options || ctrl.$options.updateOnDefault) {
25514               ctrl.$$debounceViewValueCommit(trigger);
25515             }
25516           };
25517
25518           this.$$debounceViewValueCommit = function(trigger) {
25519             var debounceDelay = 0,
25520                 options = ctrl.$options,
25521                 debounce;
25522
25523             if (options && isDefined(options.debounce)) {
25524               debounce = options.debounce;
25525               if (isNumber(debounce)) {
25526                 debounceDelay = debounce;
25527               } else if (isNumber(debounce[trigger])) {
25528                 debounceDelay = debounce[trigger];
25529               } else if (isNumber(debounce['default'])) {
25530                 debounceDelay = debounce['default'];
25531               }
25532             }
25533
25534             $timeout.cancel(pendingDebounce);
25535             if (debounceDelay) {
25536               pendingDebounce = $timeout(function() {
25537                 ctrl.$commitViewValue();
25538               }, debounceDelay);
25539             } else if ($rootScope.$$phase) {
25540               ctrl.$commitViewValue();
25541             } else {
25542               $scope.$apply(function() {
25543                 ctrl.$commitViewValue();
25544               });
25545             }
25546           };
25547
25548           // model -> value
25549           // Note: we cannot use a normal scope.$watch as we want to detect the following:
25550           // 1. scope value is 'a'
25551           // 2. user enters 'b'
25552           // 3. ng-change kicks in and reverts scope value to 'a'
25553           //    -> scope value did not change since the last digest as
25554           //       ng-change executes in apply phase
25555           // 4. view should be changed back to 'a'
25556           $scope.$watch(function ngModelWatch() {
25557             var modelValue = ngModelGet($scope);
25558
25559             // if scope model value and ngModel value are out of sync
25560             // TODO(perf): why not move this to the action fn?
25561             if (modelValue !== ctrl.$modelValue &&
25562                // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
25563                (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
25564             ) {
25565               ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
25566               parserValid = undefined;
25567
25568               var formatters = ctrl.$formatters,
25569                   idx = formatters.length;
25570
25571               var viewValue = modelValue;
25572               while (idx--) {
25573                 viewValue = formatters[idx](viewValue);
25574               }
25575               if (ctrl.$viewValue !== viewValue) {
25576                 ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
25577                 ctrl.$render();
25578
25579                 ctrl.$$runValidators(modelValue, viewValue, noop);
25580               }
25581             }
25582
25583             return modelValue;
25584           });
25585         }];
25586
25587
25588         /**
25589          * @ngdoc directive
25590          * @name ngModel
25591          *
25592          * @element input
25593          * @priority 1
25594          *
25595          * @description
25596          * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
25597          * property on the scope using {@link ngModel.NgModelController NgModelController},
25598          * which is created and exposed by this directive.
25599          *
25600          * `ngModel` is responsible for:
25601          *
25602          * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
25603          *   require.
25604          * - Providing validation behavior (i.e. required, number, email, url).
25605          * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
25606          * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.
25607          * - Registering the control with its parent {@link ng.directive:form form}.
25608          *
25609          * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
25610          * current scope. If the property doesn't already exist on this scope, it will be created
25611          * implicitly and added to the scope.
25612          *
25613          * For best practices on using `ngModel`, see:
25614          *
25615          *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
25616          *
25617          * For basic examples, how to use `ngModel`, see:
25618          *
25619          *  - {@link ng.directive:input input}
25620          *    - {@link input[text] text}
25621          *    - {@link input[checkbox] checkbox}
25622          *    - {@link input[radio] radio}
25623          *    - {@link input[number] number}
25624          *    - {@link input[email] email}
25625          *    - {@link input[url] url}
25626          *    - {@link input[date] date}
25627          *    - {@link input[datetime-local] datetime-local}
25628          *    - {@link input[time] time}
25629          *    - {@link input[month] month}
25630          *    - {@link input[week] week}
25631          *  - {@link ng.directive:select select}
25632          *  - {@link ng.directive:textarea textarea}
25633          *
25634          * # CSS classes
25635          * The following CSS classes are added and removed on the associated input/select/textarea element
25636          * depending on the validity of the model.
25637          *
25638          *  - `ng-valid`: the model is valid
25639          *  - `ng-invalid`: the model is invalid
25640          *  - `ng-valid-[key]`: for each valid key added by `$setValidity`
25641          *  - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
25642          *  - `ng-pristine`: the control hasn't been interacted with yet
25643          *  - `ng-dirty`: the control has been interacted with
25644          *  - `ng-touched`: the control has been blurred
25645          *  - `ng-untouched`: the control hasn't been blurred
25646          *  - `ng-pending`: any `$asyncValidators` are unfulfilled
25647          *
25648          * Keep in mind that ngAnimate can detect each of these classes when added and removed.
25649          *
25650          * ## Animation Hooks
25651          *
25652          * Animations within models are triggered when any of the associated CSS classes are added and removed
25653          * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
25654          * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
25655          * The animations that are triggered within ngModel are similar to how they work in ngClass and
25656          * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
25657          *
25658          * The following example shows a simple way to utilize CSS transitions to style an input element
25659          * that has been rendered as invalid after it has been validated:
25660          *
25661          * <pre>
25662          * //be sure to include ngAnimate as a module to hook into more
25663          * //advanced animations
25664          * .my-input {
25665          *   transition:0.5s linear all;
25666          *   background: white;
25667          * }
25668          * .my-input.ng-invalid {
25669          *   background: red;
25670          *   color:white;
25671          * }
25672          * </pre>
25673          *
25674          * @example
25675          * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
25676              <file name="index.html">
25677                <script>
25678                 angular.module('inputExample', [])
25679                   .controller('ExampleController', ['$scope', function($scope) {
25680                     $scope.val = '1';
25681                   }]);
25682                </script>
25683                <style>
25684                  .my-input {
25685                    transition:all linear 0.5s;
25686                    background: transparent;
25687                  }
25688                  .my-input.ng-invalid {
25689                    color:white;
25690                    background: red;
25691                  }
25692                </style>
25693                <p id="inputDescription">
25694                 Update input to see transitions when valid/invalid.
25695                 Integer is a valid value.
25696                </p>
25697                <form name="testForm" ng-controller="ExampleController">
25698                  <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input"
25699                         aria-describedby="inputDescription" />
25700                </form>
25701              </file>
25702          * </example>
25703          *
25704          * ## Binding to a getter/setter
25705          *
25706          * Sometimes it's helpful to bind `ngModel` to a getter/setter function.  A getter/setter is a
25707          * function that returns a representation of the model when called with zero arguments, and sets
25708          * the internal state of a model when called with an argument. It's sometimes useful to use this
25709          * for models that have an internal representation that's different from what the model exposes
25710          * to the view.
25711          *
25712          * <div class="alert alert-success">
25713          * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
25714          * frequently than other parts of your code.
25715          * </div>
25716          *
25717          * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
25718          * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
25719          * a `<form>`, which will enable this behavior for all `<input>`s within it. See
25720          * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
25721          *
25722          * The following example shows how to use `ngModel` with a getter/setter:
25723          *
25724          * @example
25725          * <example name="ngModel-getter-setter" module="getterSetterExample">
25726              <file name="index.html">
25727                <div ng-controller="ExampleController">
25728                  <form name="userForm">
25729                    <label>Name:
25730                      <input type="text" name="userName"
25731                             ng-model="user.name"
25732                             ng-model-options="{ getterSetter: true }" />
25733                    </label>
25734                  </form>
25735                  <pre>user.name = <span ng-bind="user.name()"></span></pre>
25736                </div>
25737              </file>
25738              <file name="app.js">
25739                angular.module('getterSetterExample', [])
25740                  .controller('ExampleController', ['$scope', function($scope) {
25741                    var _name = 'Brian';
25742                    $scope.user = {
25743                      name: function(newName) {
25744                       // Note that newName can be undefined for two reasons:
25745                       // 1. Because it is called as a getter and thus called with no arguments
25746                       // 2. Because the property should actually be set to undefined. This happens e.g. if the
25747                       //    input is invalid
25748                       return arguments.length ? (_name = newName) : _name;
25749                      }
25750                    };
25751                  }]);
25752              </file>
25753          * </example>
25754          */
25755         var ngModelDirective = ['$rootScope', function($rootScope) {
25756           return {
25757             restrict: 'A',
25758             require: ['ngModel', '^?form', '^?ngModelOptions'],
25759             controller: NgModelController,
25760             // Prelink needs to run before any input directive
25761             // so that we can set the NgModelOptions in NgModelController
25762             // before anyone else uses it.
25763             priority: 1,
25764             compile: function ngModelCompile(element) {
25765               // Setup initial state of the control
25766               element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);
25767
25768               return {
25769                 pre: function ngModelPreLink(scope, element, attr, ctrls) {
25770                   var modelCtrl = ctrls[0],
25771                       formCtrl = ctrls[1] || modelCtrl.$$parentForm;
25772
25773                   modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
25774
25775                   // notify others, especially parent forms
25776                   formCtrl.$addControl(modelCtrl);
25777
25778                   attr.$observe('name', function(newValue) {
25779                     if (modelCtrl.$name !== newValue) {
25780                       modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);
25781                     }
25782                   });
25783
25784                   scope.$on('$destroy', function() {
25785                     modelCtrl.$$parentForm.$removeControl(modelCtrl);
25786                   });
25787                 },
25788                 post: function ngModelPostLink(scope, element, attr, ctrls) {
25789                   var modelCtrl = ctrls[0];
25790                   if (modelCtrl.$options && modelCtrl.$options.updateOn) {
25791                     element.on(modelCtrl.$options.updateOn, function(ev) {
25792                       modelCtrl.$$debounceViewValueCommit(ev && ev.type);
25793                     });
25794                   }
25795
25796                   element.on('blur', function(ev) {
25797                     if (modelCtrl.$touched) return;
25798
25799                     if ($rootScope.$$phase) {
25800                       scope.$evalAsync(modelCtrl.$setTouched);
25801                     } else {
25802                       scope.$apply(modelCtrl.$setTouched);
25803                     }
25804                   });
25805                 }
25806               };
25807             }
25808           };
25809         }];
25810
25811         var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
25812
25813         /**
25814          * @ngdoc directive
25815          * @name ngModelOptions
25816          *
25817          * @description
25818          * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of
25819          * events that will trigger a model update and/or a debouncing delay so that the actual update only
25820          * takes place when a timer expires; this timer will be reset after another change takes place.
25821          *
25822          * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might
25823          * be different from the value in the actual model. This means that if you update the model you
25824          * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in
25825          * order to make sure it is synchronized with the model and that any debounced action is canceled.
25826          *
25827          * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}
25828          * method is by making sure the input is placed inside a form that has a `name` attribute. This is
25829          * important because `form` controllers are published to the related scope under the name in their
25830          * `name` attribute.
25831          *
25832          * Any pending changes will take place immediately when an enclosing form is submitted via the
25833          * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
25834          * to have access to the updated model.
25835          *
25836          * `ngModelOptions` has an effect on the element it's declared on and its descendants.
25837          *
25838          * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
25839          *   - `updateOn`: string specifying which event should the input be bound to. You can set several
25840          *     events using an space delimited list. There is a special event called `default` that
25841          *     matches the default events belonging of the control.
25842          *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A
25843          *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
25844          *     custom value for each event. For example:
25845          *     `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"`
25846          *   - `allowInvalid`: boolean value which indicates that the model can be set with values that did
25847          *     not validate correctly instead of the default behavior of setting the model to undefined.
25848          *   - `getterSetter`: boolean value which determines whether or not to treat functions bound to
25849                `ngModel` as getters/setters.
25850          *   - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for
25851          *     `<input type="date">`, `<input type="time">`, ... . It understands UTC/GMT and the
25852          *     continental US time zone abbreviations, but for general use, use a time zone offset, for
25853          *     example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
25854          *     If not specified, the timezone of the browser will be used.
25855          *
25856          * @example
25857
25858           The following example shows how to override immediate updates. Changes on the inputs within the
25859           form will update the model only when the control loses focus (blur event). If `escape` key is
25860           pressed while the input field is focused, the value is reset to the value in the current model.
25861
25862           <example name="ngModelOptions-directive-blur" module="optionsExample">
25863             <file name="index.html">
25864               <div ng-controller="ExampleController">
25865                 <form name="userForm">
25866                   <label>Name:
25867                     <input type="text" name="userName"
25868                            ng-model="user.name"
25869                            ng-model-options="{ updateOn: 'blur' }"
25870                            ng-keyup="cancel($event)" />
25871                   </label><br />
25872                   <label>Other data:
25873                     <input type="text" ng-model="user.data" />
25874                   </label><br />
25875                 </form>
25876                 <pre>user.name = <span ng-bind="user.name"></span></pre>
25877                 <pre>user.data = <span ng-bind="user.data"></span></pre>
25878               </div>
25879             </file>
25880             <file name="app.js">
25881               angular.module('optionsExample', [])
25882                 .controller('ExampleController', ['$scope', function($scope) {
25883                   $scope.user = { name: 'John', data: '' };
25884
25885                   $scope.cancel = function(e) {
25886                     if (e.keyCode == 27) {
25887                       $scope.userForm.userName.$rollbackViewValue();
25888                     }
25889                   };
25890                 }]);
25891             </file>
25892             <file name="protractor.js" type="protractor">
25893               var model = element(by.binding('user.name'));
25894               var input = element(by.model('user.name'));
25895               var other = element(by.model('user.data'));
25896
25897               it('should allow custom events', function() {
25898                 input.sendKeys(' Doe');
25899                 input.click();
25900                 expect(model.getText()).toEqual('John');
25901                 other.click();
25902                 expect(model.getText()).toEqual('John Doe');
25903               });
25904
25905               it('should $rollbackViewValue when model changes', function() {
25906                 input.sendKeys(' Doe');
25907                 expect(input.getAttribute('value')).toEqual('John Doe');
25908                 input.sendKeys(protractor.Key.ESCAPE);
25909                 expect(input.getAttribute('value')).toEqual('John');
25910                 other.click();
25911                 expect(model.getText()).toEqual('John');
25912               });
25913             </file>
25914           </example>
25915
25916           This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
25917           If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
25918
25919           <example name="ngModelOptions-directive-debounce" module="optionsExample">
25920             <file name="index.html">
25921               <div ng-controller="ExampleController">
25922                 <form name="userForm">
25923                   <label>Name:
25924                     <input type="text" name="userName"
25925                            ng-model="user.name"
25926                            ng-model-options="{ debounce: 1000 }" />
25927                   </label>
25928                   <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button>
25929                   <br />
25930                 </form>
25931                 <pre>user.name = <span ng-bind="user.name"></span></pre>
25932               </div>
25933             </file>
25934             <file name="app.js">
25935               angular.module('optionsExample', [])
25936                 .controller('ExampleController', ['$scope', function($scope) {
25937                   $scope.user = { name: 'Igor' };
25938                 }]);
25939             </file>
25940           </example>
25941
25942           This one shows how to bind to getter/setters:
25943
25944           <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
25945             <file name="index.html">
25946               <div ng-controller="ExampleController">
25947                 <form name="userForm">
25948                   <label>Name:
25949                     <input type="text" name="userName"
25950                            ng-model="user.name"
25951                            ng-model-options="{ getterSetter: true }" />
25952                   </label>
25953                 </form>
25954                 <pre>user.name = <span ng-bind="user.name()"></span></pre>
25955               </div>
25956             </file>
25957             <file name="app.js">
25958               angular.module('getterSetterExample', [])
25959                 .controller('ExampleController', ['$scope', function($scope) {
25960                   var _name = 'Brian';
25961                   $scope.user = {
25962                     name: function(newName) {
25963                       // Note that newName can be undefined for two reasons:
25964                       // 1. Because it is called as a getter and thus called with no arguments
25965                       // 2. Because the property should actually be set to undefined. This happens e.g. if the
25966                       //    input is invalid
25967                       return arguments.length ? (_name = newName) : _name;
25968                     }
25969                   };
25970                 }]);
25971             </file>
25972           </example>
25973          */
25974         var ngModelOptionsDirective = function() {
25975           return {
25976             restrict: 'A',
25977             controller: ['$scope', '$attrs', function($scope, $attrs) {
25978               var that = this;
25979               this.$options = copy($scope.$eval($attrs.ngModelOptions));
25980               // Allow adding/overriding bound events
25981               if (isDefined(this.$options.updateOn)) {
25982                 this.$options.updateOnDefault = false;
25983                 // extract "default" pseudo-event from list of events that can trigger a model update
25984                 this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
25985                   that.$options.updateOnDefault = true;
25986                   return ' ';
25987                 }));
25988               } else {
25989                 this.$options.updateOnDefault = true;
25990               }
25991             }]
25992           };
25993         };
25994
25995
25996
25997         // helper methods
25998         function addSetValidityMethod(context) {
25999           var ctrl = context.ctrl,
26000               $element = context.$element,
26001               classCache = {},
26002               set = context.set,
26003               unset = context.unset,
26004               $animate = context.$animate;
26005
26006           classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
26007
26008           ctrl.$setValidity = setValidity;
26009
26010           function setValidity(validationErrorKey, state, controller) {
26011             if (isUndefined(state)) {
26012               createAndSet('$pending', validationErrorKey, controller);
26013             } else {
26014               unsetAndCleanup('$pending', validationErrorKey, controller);
26015             }
26016             if (!isBoolean(state)) {
26017               unset(ctrl.$error, validationErrorKey, controller);
26018               unset(ctrl.$$success, validationErrorKey, controller);
26019             } else {
26020               if (state) {
26021                 unset(ctrl.$error, validationErrorKey, controller);
26022                 set(ctrl.$$success, validationErrorKey, controller);
26023               } else {
26024                 set(ctrl.$error, validationErrorKey, controller);
26025                 unset(ctrl.$$success, validationErrorKey, controller);
26026               }
26027             }
26028             if (ctrl.$pending) {
26029               cachedToggleClass(PENDING_CLASS, true);
26030               ctrl.$valid = ctrl.$invalid = undefined;
26031               toggleValidationCss('', null);
26032             } else {
26033               cachedToggleClass(PENDING_CLASS, false);
26034               ctrl.$valid = isObjectEmpty(ctrl.$error);
26035               ctrl.$invalid = !ctrl.$valid;
26036               toggleValidationCss('', ctrl.$valid);
26037             }
26038
26039             // re-read the state as the set/unset methods could have
26040             // combined state in ctrl.$error[validationError] (used for forms),
26041             // where setting/unsetting only increments/decrements the value,
26042             // and does not replace it.
26043             var combinedState;
26044             if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {
26045               combinedState = undefined;
26046             } else if (ctrl.$error[validationErrorKey]) {
26047               combinedState = false;
26048             } else if (ctrl.$$success[validationErrorKey]) {
26049               combinedState = true;
26050             } else {
26051               combinedState = null;
26052             }
26053
26054             toggleValidationCss(validationErrorKey, combinedState);
26055             ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
26056           }
26057
26058           function createAndSet(name, value, controller) {
26059             if (!ctrl[name]) {
26060               ctrl[name] = {};
26061             }
26062             set(ctrl[name], value, controller);
26063           }
26064
26065           function unsetAndCleanup(name, value, controller) {
26066             if (ctrl[name]) {
26067               unset(ctrl[name], value, controller);
26068             }
26069             if (isObjectEmpty(ctrl[name])) {
26070               ctrl[name] = undefined;
26071             }
26072           }
26073
26074           function cachedToggleClass(className, switchValue) {
26075             if (switchValue && !classCache[className]) {
26076               $animate.addClass($element, className);
26077               classCache[className] = true;
26078             } else if (!switchValue && classCache[className]) {
26079               $animate.removeClass($element, className);
26080               classCache[className] = false;
26081             }
26082           }
26083
26084           function toggleValidationCss(validationErrorKey, isValid) {
26085             validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
26086
26087             cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);
26088             cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);
26089           }
26090         }
26091
26092         function isObjectEmpty(obj) {
26093           if (obj) {
26094             for (var prop in obj) {
26095               if (obj.hasOwnProperty(prop)) {
26096                 return false;
26097               }
26098             }
26099           }
26100           return true;
26101         }
26102
26103         /**
26104          * @ngdoc directive
26105          * @name ngNonBindable
26106          * @restrict AC
26107          * @priority 1000
26108          *
26109          * @description
26110          * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
26111          * DOM element. This is useful if the element contains what appears to be Angular directives and
26112          * bindings but which should be ignored by Angular. This could be the case if you have a site that
26113          * displays snippets of code, for instance.
26114          *
26115          * @element ANY
26116          *
26117          * @example
26118          * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
26119          * but the one wrapped in `ngNonBindable` is left alone.
26120          *
26121          * @example
26122             <example>
26123               <file name="index.html">
26124                 <div>Normal: {{1 + 2}}</div>
26125                 <div ng-non-bindable>Ignored: {{1 + 2}}</div>
26126               </file>
26127               <file name="protractor.js" type="protractor">
26128                it('should check ng-non-bindable', function() {
26129                  expect(element(by.binding('1 + 2')).getText()).toContain('3');
26130                  expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
26131                });
26132               </file>
26133             </example>
26134          */
26135         var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
26136
26137         /* global jqLiteRemove */
26138
26139         var ngOptionsMinErr = minErr('ngOptions');
26140
26141         /**
26142          * @ngdoc directive
26143          * @name ngOptions
26144          * @restrict A
26145          *
26146          * @description
26147          *
26148          * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
26149          * elements for the `<select>` element using the array or object obtained by evaluating the
26150          * `ngOptions` comprehension expression.
26151          *
26152          * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
26153          * similar result. However, `ngOptions` provides some benefits such as reducing memory and
26154          * increasing speed by not creating a new scope for each repeated instance, as well as providing
26155          * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
26156          * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
26157          *  to a non-string value. This is because an option element can only be bound to string values at
26158          * present.
26159          *
26160          * When an item in the `<select>` menu is selected, the array element or object property
26161          * represented by the selected option will be bound to the model identified by the `ngModel`
26162          * directive.
26163          *
26164          * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
26165          * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
26166          * option. See example below for demonstration.
26167          *
26168          * ## Complex Models (objects or collections)
26169          *
26170          * By default, `ngModel` watches the model by reference, not value. This is important to know when
26171          * binding the select to a model that is an object or a collection.
26172          *
26173          * One issue occurs if you want to preselect an option. For example, if you set
26174          * the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,
26175          * because the objects are not identical. So by default, you should always reference the item in your collection
26176          * for preselections, e.g.: `$scope.selected = $scope.collection[3]`.
26177          *
26178          * Another solution is to use a `track by` clause, because then `ngOptions` will track the identity
26179          * of the item not by reference, but by the result of the `track by` expression. For example, if your
26180          * collection items have an id property, you would `track by item.id`.
26181          *
26182          * A different issue with objects or collections is that ngModel won't detect if an object property or
26183          * a collection item changes. For that reason, `ngOptions` additionally watches the model using
26184          * `$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.
26185          * This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection
26186          * has not changed identity, but only a property on the object or an item in the collection changes.
26187          *
26188          * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
26189          * if the model is an array). This means that changing a property deeper than the first level inside the
26190          * object/collection will not trigger a re-rendering.
26191          *
26192          * ## `select` **`as`**
26193          *
26194          * Using `select` **`as`** will bind the result of the `select` expression to the model, but
26195          * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
26196          * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
26197          * is used, the result of that expression will be set as the value of the `option` and `select` elements.
26198          *
26199          *
26200          * ### `select` **`as`** and **`track by`**
26201          *
26202          * <div class="alert alert-warning">
26203          * Be careful when using `select` **`as`** and **`track by`** in the same expression.
26204          * </div>
26205          *
26206          * Given this array of items on the $scope:
26207          *
26208          * ```js
26209          * $scope.items = [{
26210          *   id: 1,
26211          *   label: 'aLabel',
26212          *   subItem: { name: 'aSubItem' }
26213          * }, {
26214          *   id: 2,
26215          *   label: 'bLabel',
26216          *   subItem: { name: 'bSubItem' }
26217          * }];
26218          * ```
26219          *
26220          * This will work:
26221          *
26222          * ```html
26223          * <select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
26224          * ```
26225          * ```js
26226          * $scope.selected = $scope.items[0];
26227          * ```
26228          *
26229          * but this will not work:
26230          *
26231          * ```html
26232          * <select ng-options="item.subItem as item.label for item in items track by item.id" ng-model="selected"></select>
26233          * ```
26234          * ```js
26235          * $scope.selected = $scope.items[0].subItem;
26236          * ```
26237          *
26238          * In both examples, the **`track by`** expression is applied successfully to each `item` in the
26239          * `items` array. Because the selected option has been set programmatically in the controller, the
26240          * **`track by`** expression is also applied to the `ngModel` value. In the first example, the
26241          * `ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with
26242          * no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**
26243          * expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
26244          * is not matched against any `<option>` and the `<select>` appears as having no selected value.
26245          *
26246          *
26247          * @param {string} ngModel Assignable angular expression to data-bind to.
26248          * @param {string=} name Property name of the form under which the control is published.
26249          * @param {string=} required The control is considered valid only if value is entered.
26250          * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
26251          *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
26252          *    `required` when you want to data-bind to the `required` attribute.
26253          * @param {comprehension_expression=} ngOptions in one of the following forms:
26254          *
26255          *   * for array data sources:
26256          *     * `label` **`for`** `value` **`in`** `array`
26257          *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`
26258          *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
26259          *     * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array`
26260          *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
26261          *     * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
26262          *     * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
26263          *        (for including a filter with `track by`)
26264          *   * for object data sources:
26265          *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
26266          *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
26267          *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
26268          *     * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`
26269          *     * `select` **`as`** `label` **`group by`** `group`
26270          *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`
26271          *     * `select` **`as`** `label` **`disable when`** `disable`
26272          *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`
26273          *
26274          * Where:
26275          *
26276          *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.
26277          *   * `value`: local variable which will refer to each item in the `array` or each property value
26278          *      of `object` during iteration.
26279          *   * `key`: local variable which will refer to a property name in `object` during iteration.
26280          *   * `label`: The result of this expression will be the label for `<option>` element. The
26281          *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
26282          *   * `select`: The result of this expression will be bound to the model of the parent `<select>`
26283          *      element. If not specified, `select` expression will default to `value`.
26284          *   * `group`: The result of this expression will be used to group options using the `<optgroup>`
26285          *      DOM element.
26286          *   * `disable`: The result of this expression will be used to disable the rendered `<option>`
26287          *      element. Return `true` to disable.
26288          *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be
26289          *      used to identify the objects in the array. The `trackexpr` will most likely refer to the
26290          *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved
26291          *      even when the options are recreated (e.g. reloaded from the server).
26292          *
26293          * @example
26294             <example module="selectExample">
26295               <file name="index.html">
26296                 <script>
26297                 angular.module('selectExample', [])
26298                   .controller('ExampleController', ['$scope', function($scope) {
26299                     $scope.colors = [
26300                       {name:'black', shade:'dark'},
26301                       {name:'white', shade:'light', notAnOption: true},
26302                       {name:'red', shade:'dark'},
26303                       {name:'blue', shade:'dark', notAnOption: true},
26304                       {name:'yellow', shade:'light', notAnOption: false}
26305                     ];
26306                     $scope.myColor = $scope.colors[2]; // red
26307                   }]);
26308                 </script>
26309                 <div ng-controller="ExampleController">
26310                   <ul>
26311                     <li ng-repeat="color in colors">
26312                       <label>Name: <input ng-model="color.name"></label>
26313                       <label><input type="checkbox" ng-model="color.notAnOption"> Disabled?</label>
26314                       <button ng-click="colors.splice($index, 1)" aria-label="Remove">X</button>
26315                     </li>
26316                     <li>
26317                       <button ng-click="colors.push({})">add</button>
26318                     </li>
26319                   </ul>
26320                   <hr/>
26321                   <label>Color (null not allowed):
26322                     <select ng-model="myColor" ng-options="color.name for color in colors"></select>
26323                   </label><br/>
26324                   <label>Color (null allowed):
26325                   <span  class="nullable">
26326                     <select ng-model="myColor" ng-options="color.name for color in colors">
26327                       <option value="">-- choose color --</option>
26328                     </select>
26329                   </span></label><br/>
26330
26331                   <label>Color grouped by shade:
26332                     <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
26333                     </select>
26334                   </label><br/>
26335
26336                   <label>Color grouped by shade, with some disabled:
26337                     <select ng-model="myColor"
26338                           ng-options="color.name group by color.shade disable when color.notAnOption for color in colors">
26339                     </select>
26340                   </label><br/>
26341
26342
26343
26344                   Select <button ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</button>.
26345                   <br/>
26346                   <hr/>
26347                   Currently selected: {{ {selected_color:myColor} }}
26348                   <div style="border:solid 1px black; height:20px"
26349                        ng-style="{'background-color':myColor.name}">
26350                   </div>
26351                 </div>
26352               </file>
26353               <file name="protractor.js" type="protractor">
26354                  it('should check ng-options', function() {
26355                    expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
26356                    element.all(by.model('myColor')).first().click();
26357                    element.all(by.css('select[ng-model="myColor"] option')).first().click();
26358                    expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
26359                    element(by.css('.nullable select[ng-model="myColor"]')).click();
26360                    element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
26361                    expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
26362                  });
26363               </file>
26364             </example>
26365          */
26366
26367         // jshint maxlen: false
26368         //                     //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999
26369         var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
26370                                 // 1: value expression (valueFn)
26371                                 // 2: label expression (displayFn)
26372                                 // 3: group by expression (groupByFn)
26373                                 // 4: disable when expression (disableWhenFn)
26374                                 // 5: array item variable name
26375                                 // 6: object item key variable name
26376                                 // 7: object item value variable name
26377                                 // 8: collection expression
26378                                 // 9: track by expression
26379         // jshint maxlen: 100
26380
26381
26382         var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
26383
26384           function parseOptionsExpression(optionsExp, selectElement, scope) {
26385
26386             var match = optionsExp.match(NG_OPTIONS_REGEXP);
26387             if (!(match)) {
26388               throw ngOptionsMinErr('iexp',
26389                 "Expected expression in form of " +
26390                 "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
26391                 " but got '{0}'. Element: {1}",
26392                 optionsExp, startingTag(selectElement));
26393             }
26394
26395             // Extract the parts from the ngOptions expression
26396
26397             // The variable name for the value of the item in the collection
26398             var valueName = match[5] || match[7];
26399             // The variable name for the key of the item in the collection
26400             var keyName = match[6];
26401
26402             // An expression that generates the viewValue for an option if there is a label expression
26403             var selectAs = / as /.test(match[0]) && match[1];
26404             // An expression that is used to track the id of each object in the options collection
26405             var trackBy = match[9];
26406             // An expression that generates the viewValue for an option if there is no label expression
26407             var valueFn = $parse(match[2] ? match[1] : valueName);
26408             var selectAsFn = selectAs && $parse(selectAs);
26409             var viewValueFn = selectAsFn || valueFn;
26410             var trackByFn = trackBy && $parse(trackBy);
26411
26412             // Get the value by which we are going to track the option
26413             // if we have a trackFn then use that (passing scope and locals)
26414             // otherwise just hash the given viewValue
26415             var getTrackByValueFn = trackBy ?
26416                                       function(value, locals) { return trackByFn(scope, locals); } :
26417                                       function getHashOfValue(value) { return hashKey(value); };
26418             var getTrackByValue = function(value, key) {
26419               return getTrackByValueFn(value, getLocals(value, key));
26420             };
26421
26422             var displayFn = $parse(match[2] || match[1]);
26423             var groupByFn = $parse(match[3] || '');
26424             var disableWhenFn = $parse(match[4] || '');
26425             var valuesFn = $parse(match[8]);
26426
26427             var locals = {};
26428             var getLocals = keyName ? function(value, key) {
26429               locals[keyName] = key;
26430               locals[valueName] = value;
26431               return locals;
26432             } : function(value) {
26433               locals[valueName] = value;
26434               return locals;
26435             };
26436
26437
26438             function Option(selectValue, viewValue, label, group, disabled) {
26439               this.selectValue = selectValue;
26440               this.viewValue = viewValue;
26441               this.label = label;
26442               this.group = group;
26443               this.disabled = disabled;
26444             }
26445
26446             function getOptionValuesKeys(optionValues) {
26447               var optionValuesKeys;
26448
26449               if (!keyName && isArrayLike(optionValues)) {
26450                 optionValuesKeys = optionValues;
26451               } else {
26452                 // if object, extract keys, in enumeration order, unsorted
26453                 optionValuesKeys = [];
26454                 for (var itemKey in optionValues) {
26455                   if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
26456                     optionValuesKeys.push(itemKey);
26457                   }
26458                 }
26459               }
26460               return optionValuesKeys;
26461             }
26462
26463             return {
26464               trackBy: trackBy,
26465               getTrackByValue: getTrackByValue,
26466               getWatchables: $parse(valuesFn, function(optionValues) {
26467                 // Create a collection of things that we would like to watch (watchedArray)
26468                 // so that they can all be watched using a single $watchCollection
26469                 // that only runs the handler once if anything changes
26470                 var watchedArray = [];
26471                 optionValues = optionValues || [];
26472
26473                 var optionValuesKeys = getOptionValuesKeys(optionValues);
26474                 var optionValuesLength = optionValuesKeys.length;
26475                 for (var index = 0; index < optionValuesLength; index++) {
26476                   var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
26477                   var value = optionValues[key];
26478
26479                   var locals = getLocals(optionValues[key], key);
26480                   var selectValue = getTrackByValueFn(optionValues[key], locals);
26481                   watchedArray.push(selectValue);
26482
26483                   // Only need to watch the displayFn if there is a specific label expression
26484                   if (match[2] || match[1]) {
26485                     var label = displayFn(scope, locals);
26486                     watchedArray.push(label);
26487                   }
26488
26489                   // Only need to watch the disableWhenFn if there is a specific disable expression
26490                   if (match[4]) {
26491                     var disableWhen = disableWhenFn(scope, locals);
26492                     watchedArray.push(disableWhen);
26493                   }
26494                 }
26495                 return watchedArray;
26496               }),
26497
26498               getOptions: function() {
26499
26500                 var optionItems = [];
26501                 var selectValueMap = {};
26502
26503                 // The option values were already computed in the `getWatchables` fn,
26504                 // which must have been called to trigger `getOptions`
26505                 var optionValues = valuesFn(scope) || [];
26506                 var optionValuesKeys = getOptionValuesKeys(optionValues);
26507                 var optionValuesLength = optionValuesKeys.length;
26508
26509                 for (var index = 0; index < optionValuesLength; index++) {
26510                   var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
26511                   var value = optionValues[key];
26512                   var locals = getLocals(value, key);
26513                   var viewValue = viewValueFn(scope, locals);
26514                   var selectValue = getTrackByValueFn(viewValue, locals);
26515                   var label = displayFn(scope, locals);
26516                   var group = groupByFn(scope, locals);
26517                   var disabled = disableWhenFn(scope, locals);
26518                   var optionItem = new Option(selectValue, viewValue, label, group, disabled);
26519
26520                   optionItems.push(optionItem);
26521                   selectValueMap[selectValue] = optionItem;
26522                 }
26523
26524                 return {
26525                   items: optionItems,
26526                   selectValueMap: selectValueMap,
26527                   getOptionFromViewValue: function(value) {
26528                     return selectValueMap[getTrackByValue(value)];
26529                   },
26530                   getViewValueFromOption: function(option) {
26531                     // If the viewValue could be an object that may be mutated by the application,
26532                     // we need to make a copy and not return the reference to the value on the option.
26533                     return trackBy ? angular.copy(option.viewValue) : option.viewValue;
26534                   }
26535                 };
26536               }
26537             };
26538           }
26539
26540
26541           // we can't just jqLite('<option>') since jqLite is not smart enough
26542           // to create it in <select> and IE barfs otherwise.
26543           var optionTemplate = document.createElement('option'),
26544               optGroupTemplate = document.createElement('optgroup');
26545
26546
26547             function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
26548
26549               // if ngModel is not defined, we don't need to do anything
26550               var ngModelCtrl = ctrls[1];
26551               if (!ngModelCtrl) return;
26552
26553               var selectCtrl = ctrls[0];
26554               var multiple = attr.multiple;
26555
26556               // The emptyOption allows the application developer to provide their own custom "empty"
26557               // option when the viewValue does not match any of the option values.
26558               var emptyOption;
26559               for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) {
26560                 if (children[i].value === '') {
26561                   emptyOption = children.eq(i);
26562                   break;
26563                 }
26564               }
26565
26566               var providedEmptyOption = !!emptyOption;
26567
26568               var unknownOption = jqLite(optionTemplate.cloneNode(false));
26569               unknownOption.val('?');
26570
26571               var options;
26572               var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope);
26573
26574
26575               var renderEmptyOption = function() {
26576                 if (!providedEmptyOption) {
26577                   selectElement.prepend(emptyOption);
26578                 }
26579                 selectElement.val('');
26580                 emptyOption.prop('selected', true); // needed for IE
26581                 emptyOption.attr('selected', true);
26582               };
26583
26584               var removeEmptyOption = function() {
26585                 if (!providedEmptyOption) {
26586                   emptyOption.remove();
26587                 }
26588               };
26589
26590
26591               var renderUnknownOption = function() {
26592                 selectElement.prepend(unknownOption);
26593                 selectElement.val('?');
26594                 unknownOption.prop('selected', true); // needed for IE
26595                 unknownOption.attr('selected', true);
26596               };
26597
26598               var removeUnknownOption = function() {
26599                 unknownOption.remove();
26600               };
26601
26602               // Update the controller methods for multiple selectable options
26603               if (!multiple) {
26604
26605                 selectCtrl.writeValue = function writeNgOptionsValue(value) {
26606                   var option = options.getOptionFromViewValue(value);
26607
26608                   if (option && !option.disabled) {
26609                     if (selectElement[0].value !== option.selectValue) {
26610                       removeUnknownOption();
26611                       removeEmptyOption();
26612
26613                       selectElement[0].value = option.selectValue;
26614                       option.element.selected = true;
26615                       option.element.setAttribute('selected', 'selected');
26616                     }
26617                   } else {
26618                     if (value === null || providedEmptyOption) {
26619                       removeUnknownOption();
26620                       renderEmptyOption();
26621                     } else {
26622                       removeEmptyOption();
26623                       renderUnknownOption();
26624                     }
26625                   }
26626                 };
26627
26628                 selectCtrl.readValue = function readNgOptionsValue() {
26629
26630                   var selectedOption = options.selectValueMap[selectElement.val()];
26631
26632                   if (selectedOption && !selectedOption.disabled) {
26633                     removeEmptyOption();
26634                     removeUnknownOption();
26635                     return options.getViewValueFromOption(selectedOption);
26636                   }
26637                   return null;
26638                 };
26639
26640                 // If we are using `track by` then we must watch the tracked value on the model
26641                 // since ngModel only watches for object identity change
26642                 if (ngOptions.trackBy) {
26643                   scope.$watch(
26644                     function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); },
26645                     function() { ngModelCtrl.$render(); }
26646                   );
26647                 }
26648
26649               } else {
26650
26651                 ngModelCtrl.$isEmpty = function(value) {
26652                   return !value || value.length === 0;
26653                 };
26654
26655
26656                 selectCtrl.writeValue = function writeNgOptionsMultiple(value) {
26657                   options.items.forEach(function(option) {
26658                     option.element.selected = false;
26659                   });
26660
26661                   if (value) {
26662                     value.forEach(function(item) {
26663                       var option = options.getOptionFromViewValue(item);
26664                       if (option && !option.disabled) option.element.selected = true;
26665                     });
26666                   }
26667                 };
26668
26669
26670                 selectCtrl.readValue = function readNgOptionsMultiple() {
26671                   var selectedValues = selectElement.val() || [],
26672                       selections = [];
26673
26674                   forEach(selectedValues, function(value) {
26675                     var option = options.selectValueMap[value];
26676                     if (option && !option.disabled) selections.push(options.getViewValueFromOption(option));
26677                   });
26678
26679                   return selections;
26680                 };
26681
26682                 // If we are using `track by` then we must watch these tracked values on the model
26683                 // since ngModel only watches for object identity change
26684                 if (ngOptions.trackBy) {
26685
26686                   scope.$watchCollection(function() {
26687                     if (isArray(ngModelCtrl.$viewValue)) {
26688                       return ngModelCtrl.$viewValue.map(function(value) {
26689                         return ngOptions.getTrackByValue(value);
26690                       });
26691                     }
26692                   }, function() {
26693                     ngModelCtrl.$render();
26694                   });
26695
26696                 }
26697               }
26698
26699
26700               if (providedEmptyOption) {
26701
26702                 // we need to remove it before calling selectElement.empty() because otherwise IE will
26703                 // remove the label from the element. wtf?
26704                 emptyOption.remove();
26705
26706                 // compile the element since there might be bindings in it
26707                 $compile(emptyOption)(scope);
26708
26709                 // remove the class, which is added automatically because we recompile the element and it
26710                 // becomes the compilation root
26711                 emptyOption.removeClass('ng-scope');
26712               } else {
26713                 emptyOption = jqLite(optionTemplate.cloneNode(false));
26714               }
26715
26716               // We need to do this here to ensure that the options object is defined
26717               // when we first hit it in writeNgOptionsValue
26718               updateOptions();
26719
26720               // We will re-render the option elements if the option values or labels change
26721               scope.$watchCollection(ngOptions.getWatchables, updateOptions);
26722
26723               // ------------------------------------------------------------------ //
26724
26725
26726               function updateOptionElement(option, element) {
26727                 option.element = element;
26728                 element.disabled = option.disabled;
26729                 // NOTE: The label must be set before the value, otherwise IE10/11/EDGE create unresponsive
26730                 // selects in certain circumstances when multiple selects are next to each other and display
26731                 // the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
26732                 // See https://github.com/angular/angular.js/issues/11314 for more info.
26733                 // This is unfortunately untestable with unit / e2e tests
26734                 if (option.label !== element.label) {
26735                   element.label = option.label;
26736                   element.textContent = option.label;
26737                 }
26738                 if (option.value !== element.value) element.value = option.selectValue;
26739               }
26740
26741               function addOrReuseElement(parent, current, type, templateElement) {
26742                 var element;
26743                 // Check whether we can reuse the next element
26744                 if (current && lowercase(current.nodeName) === type) {
26745                   // The next element is the right type so reuse it
26746                   element = current;
26747                 } else {
26748                   // The next element is not the right type so create a new one
26749                   element = templateElement.cloneNode(false);
26750                   if (!current) {
26751                     // There are no more elements so just append it to the select
26752                     parent.appendChild(element);
26753                   } else {
26754                     // The next element is not a group so insert the new one
26755                     parent.insertBefore(element, current);
26756                   }
26757                 }
26758                 return element;
26759               }
26760
26761
26762               function removeExcessElements(current) {
26763                 var next;
26764                 while (current) {
26765                   next = current.nextSibling;
26766                   jqLiteRemove(current);
26767                   current = next;
26768                 }
26769               }
26770
26771
26772               function skipEmptyAndUnknownOptions(current) {
26773                 var emptyOption_ = emptyOption && emptyOption[0];
26774                 var unknownOption_ = unknownOption && unknownOption[0];
26775
26776                 // We cannot rely on the extracted empty option being the same as the compiled empty option,
26777                 // because the compiled empty option might have been replaced by a comment because
26778                 // it had an "element" transclusion directive on it (such as ngIf)
26779                 if (emptyOption_ || unknownOption_) {
26780                   while (current &&
26781                         (current === emptyOption_ ||
26782                         current === unknownOption_ ||
26783                         current.nodeType === NODE_TYPE_COMMENT ||
26784                         current.value === '')) {
26785                     current = current.nextSibling;
26786                   }
26787                 }
26788                 return current;
26789               }
26790
26791
26792               function updateOptions() {
26793
26794                 var previousValue = options && selectCtrl.readValue();
26795
26796                 options = ngOptions.getOptions();
26797
26798                 var groupMap = {};
26799                 var currentElement = selectElement[0].firstChild;
26800
26801                 // Ensure that the empty option is always there if it was explicitly provided
26802                 if (providedEmptyOption) {
26803                   selectElement.prepend(emptyOption);
26804                 }
26805
26806                 currentElement = skipEmptyAndUnknownOptions(currentElement);
26807
26808                 options.items.forEach(function updateOption(option) {
26809                   var group;
26810                   var groupElement;
26811                   var optionElement;
26812
26813                   if (option.group) {
26814
26815                     // This option is to live in a group
26816                     // See if we have already created this group
26817                     group = groupMap[option.group];
26818
26819                     if (!group) {
26820
26821                       // We have not already created this group
26822                       groupElement = addOrReuseElement(selectElement[0],
26823                                                        currentElement,
26824                                                        'optgroup',
26825                                                        optGroupTemplate);
26826                       // Move to the next element
26827                       currentElement = groupElement.nextSibling;
26828
26829                       // Update the label on the group element
26830                       groupElement.label = option.group;
26831
26832                       // Store it for use later
26833                       group = groupMap[option.group] = {
26834                         groupElement: groupElement,
26835                         currentOptionElement: groupElement.firstChild
26836                       };
26837
26838                     }
26839
26840                     // So now we have a group for this option we add the option to the group
26841                     optionElement = addOrReuseElement(group.groupElement,
26842                                                       group.currentOptionElement,
26843                                                       'option',
26844                                                       optionTemplate);
26845                     updateOptionElement(option, optionElement);
26846                     // Move to the next element
26847                     group.currentOptionElement = optionElement.nextSibling;
26848
26849                   } else {
26850
26851                     // This option is not in a group
26852                     optionElement = addOrReuseElement(selectElement[0],
26853                                                       currentElement,
26854                                                       'option',
26855                                                       optionTemplate);
26856                     updateOptionElement(option, optionElement);
26857                     // Move to the next element
26858                     currentElement = optionElement.nextSibling;
26859                   }
26860                 });
26861
26862
26863                 // Now remove all excess options and group
26864                 Object.keys(groupMap).forEach(function(key) {
26865                   removeExcessElements(groupMap[key].currentOptionElement);
26866                 });
26867                 removeExcessElements(currentElement);
26868
26869                 ngModelCtrl.$render();
26870
26871                 // Check to see if the value has changed due to the update to the options
26872                 if (!ngModelCtrl.$isEmpty(previousValue)) {
26873                   var nextValue = selectCtrl.readValue();
26874                   if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
26875                     ngModelCtrl.$setViewValue(nextValue);
26876                     ngModelCtrl.$render();
26877                   }
26878                 }
26879
26880               }
26881           }
26882
26883           return {
26884             restrict: 'A',
26885             terminal: true,
26886             require: ['select', '?ngModel'],
26887             link: {
26888               pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
26889                 // Deactivate the SelectController.register method to prevent
26890                 // option directives from accidentally registering themselves
26891                 // (and unwanted $destroy handlers etc.)
26892                 ctrls[0].registerOption = noop;
26893               },
26894               post: ngOptionsPostLink
26895             }
26896           };
26897         }];
26898
26899         /**
26900          * @ngdoc directive
26901          * @name ngPluralize
26902          * @restrict EA
26903          *
26904          * @description
26905          * `ngPluralize` is a directive that displays messages according to en-US localization rules.
26906          * These rules are bundled with angular.js, but can be overridden
26907          * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
26908          * by specifying the mappings between
26909          * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
26910          * and the strings to be displayed.
26911          *
26912          * # Plural categories and explicit number rules
26913          * There are two
26914          * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
26915          * in Angular's default en-US locale: "one" and "other".
26916          *
26917          * While a plural category may match many numbers (for example, in en-US locale, "other" can match
26918          * any number that is not 1), an explicit number rule can only match one number. For example, the
26919          * explicit number rule for "3" matches the number 3. There are examples of plural categories
26920          * and explicit number rules throughout the rest of this documentation.
26921          *
26922          * # Configuring ngPluralize
26923          * You configure ngPluralize by providing 2 attributes: `count` and `when`.
26924          * You can also provide an optional attribute, `offset`.
26925          *
26926          * The value of the `count` attribute can be either a string or an {@link guide/expression
26927          * Angular expression}; these are evaluated on the current scope for its bound value.
26928          *
26929          * The `when` attribute specifies the mappings between plural categories and the actual
26930          * string to be displayed. The value of the attribute should be a JSON object.
26931          *
26932          * The following example shows how to configure ngPluralize:
26933          *
26934          * ```html
26935          * <ng-pluralize count="personCount"
26936                          when="{'0': 'Nobody is viewing.',
26937          *                      'one': '1 person is viewing.',
26938          *                      'other': '{} people are viewing.'}">
26939          * </ng-pluralize>
26940          *```
26941          *
26942          * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
26943          * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
26944          * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
26945          * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
26946          * show "a dozen people are viewing".
26947          *
26948          * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
26949          * into pluralized strings. In the previous example, Angular will replace `{}` with
26950          * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
26951          * for <span ng-non-bindable>{{numberExpression}}</span>.
26952          *
26953          * If no rule is defined for a category, then an empty string is displayed and a warning is generated.
26954          * Note that some locales define more categories than `one` and `other`. For example, fr-fr defines `few` and `many`.
26955          *
26956          * # Configuring ngPluralize with offset
26957          * The `offset` attribute allows further customization of pluralized text, which can result in
26958          * a better user experience. For example, instead of the message "4 people are viewing this document",
26959          * you might display "John, Kate and 2 others are viewing this document".
26960          * The offset attribute allows you to offset a number by any desired value.
26961          * Let's take a look at an example:
26962          *
26963          * ```html
26964          * <ng-pluralize count="personCount" offset=2
26965          *               when="{'0': 'Nobody is viewing.',
26966          *                      '1': '{{person1}} is viewing.',
26967          *                      '2': '{{person1}} and {{person2}} are viewing.',
26968          *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',
26969          *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
26970          * </ng-pluralize>
26971          * ```
26972          *
26973          * Notice that we are still using two plural categories(one, other), but we added
26974          * three explicit number rules 0, 1 and 2.
26975          * When one person, perhaps John, views the document, "John is viewing" will be shown.
26976          * When three people view the document, no explicit number rule is found, so
26977          * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
26978          * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
26979          * is shown.
26980          *
26981          * Note that when you specify offsets, you must provide explicit number rules for
26982          * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
26983          * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
26984          * plural categories "one" and "other".
26985          *
26986          * @param {string|expression} count The variable to be bound to.
26987          * @param {string} when The mapping between plural category to its corresponding strings.
26988          * @param {number=} offset Offset to deduct from the total number.
26989          *
26990          * @example
26991             <example module="pluralizeExample">
26992               <file name="index.html">
26993                 <script>
26994                   angular.module('pluralizeExample', [])
26995                     .controller('ExampleController', ['$scope', function($scope) {
26996                       $scope.person1 = 'Igor';
26997                       $scope.person2 = 'Misko';
26998                       $scope.personCount = 1;
26999                     }]);
27000                 </script>
27001                 <div ng-controller="ExampleController">
27002                   <label>Person 1:<input type="text" ng-model="person1" value="Igor" /></label><br/>
27003                   <label>Person 2:<input type="text" ng-model="person2" value="Misko" /></label><br/>
27004                   <label>Number of People:<input type="text" ng-model="personCount" value="1" /></label><br/>
27005
27006                   <!--- Example with simple pluralization rules for en locale --->
27007                   Without Offset:
27008                   <ng-pluralize count="personCount"
27009                                 when="{'0': 'Nobody is viewing.',
27010                                        'one': '1 person is viewing.',
27011                                        'other': '{} people are viewing.'}">
27012                   </ng-pluralize><br>
27013
27014                   <!--- Example with offset --->
27015                   With Offset(2):
27016                   <ng-pluralize count="personCount" offset=2
27017                                 when="{'0': 'Nobody is viewing.',
27018                                        '1': '{{person1}} is viewing.',
27019                                        '2': '{{person1}} and {{person2}} are viewing.',
27020                                        'one': '{{person1}}, {{person2}} and one other person are viewing.',
27021                                        'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
27022                   </ng-pluralize>
27023                 </div>
27024               </file>
27025               <file name="protractor.js" type="protractor">
27026                 it('should show correct pluralized string', function() {
27027                   var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
27028                   var withOffset = element.all(by.css('ng-pluralize')).get(1);
27029                   var countInput = element(by.model('personCount'));
27030
27031                   expect(withoutOffset.getText()).toEqual('1 person is viewing.');
27032                   expect(withOffset.getText()).toEqual('Igor is viewing.');
27033
27034                   countInput.clear();
27035                   countInput.sendKeys('0');
27036
27037                   expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
27038                   expect(withOffset.getText()).toEqual('Nobody is viewing.');
27039
27040                   countInput.clear();
27041                   countInput.sendKeys('2');
27042
27043                   expect(withoutOffset.getText()).toEqual('2 people are viewing.');
27044                   expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');
27045
27046                   countInput.clear();
27047                   countInput.sendKeys('3');
27048
27049                   expect(withoutOffset.getText()).toEqual('3 people are viewing.');
27050                   expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');
27051
27052                   countInput.clear();
27053                   countInput.sendKeys('4');
27054
27055                   expect(withoutOffset.getText()).toEqual('4 people are viewing.');
27056                   expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
27057                 });
27058                 it('should show data-bound names', function() {
27059                   var withOffset = element.all(by.css('ng-pluralize')).get(1);
27060                   var personCount = element(by.model('personCount'));
27061                   var person1 = element(by.model('person1'));
27062                   var person2 = element(by.model('person2'));
27063                   personCount.clear();
27064                   personCount.sendKeys('4');
27065                   person1.clear();
27066                   person1.sendKeys('Di');
27067                   person2.clear();
27068                   person2.sendKeys('Vojta');
27069                   expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
27070                 });
27071               </file>
27072             </example>
27073          */
27074         var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) {
27075           var BRACE = /{}/g,
27076               IS_WHEN = /^when(Minus)?(.+)$/;
27077
27078           return {
27079             link: function(scope, element, attr) {
27080               var numberExp = attr.count,
27081                   whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
27082                   offset = attr.offset || 0,
27083                   whens = scope.$eval(whenExp) || {},
27084                   whensExpFns = {},
27085                   startSymbol = $interpolate.startSymbol(),
27086                   endSymbol = $interpolate.endSymbol(),
27087                   braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
27088                   watchRemover = angular.noop,
27089                   lastCount;
27090
27091               forEach(attr, function(expression, attributeName) {
27092                 var tmpMatch = IS_WHEN.exec(attributeName);
27093                 if (tmpMatch) {
27094                   var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
27095                   whens[whenKey] = element.attr(attr.$attr[attributeName]);
27096                 }
27097               });
27098               forEach(whens, function(expression, key) {
27099                 whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
27100
27101               });
27102
27103               scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
27104                 var count = parseFloat(newVal);
27105                 var countIsNaN = isNaN(count);
27106
27107                 if (!countIsNaN && !(count in whens)) {
27108                   // If an explicit number rule such as 1, 2, 3... is defined, just use it.
27109                   // Otherwise, check it against pluralization rules in $locale service.
27110                   count = $locale.pluralCat(count - offset);
27111                 }
27112
27113                 // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
27114                 // In JS `NaN !== NaN`, so we have to exlicitly check.
27115                 if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
27116                   watchRemover();
27117                   var whenExpFn = whensExpFns[count];
27118                   if (isUndefined(whenExpFn)) {
27119                     if (newVal != null) {
27120                       $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp);
27121                     }
27122                     watchRemover = noop;
27123                     updateElementText();
27124                   } else {
27125                     watchRemover = scope.$watch(whenExpFn, updateElementText);
27126                   }
27127                   lastCount = count;
27128                 }
27129               });
27130
27131               function updateElementText(newText) {
27132                 element.text(newText || '');
27133               }
27134             }
27135           };
27136         }];
27137
27138         /**
27139          * @ngdoc directive
27140          * @name ngRepeat
27141          * @multiElement
27142          *
27143          * @description
27144          * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
27145          * instance gets its own scope, where the given loop variable is set to the current collection item,
27146          * and `$index` is set to the item index or key.
27147          *
27148          * Special properties are exposed on the local scope of each template instance, including:
27149          *
27150          * | Variable  | Type            | Details                                                                     |
27151          * |-----------|-----------------|-----------------------------------------------------------------------------|
27152          * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |
27153          * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |
27154          * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
27155          * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |
27156          * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |
27157          * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |
27158          *
27159          * <div class="alert alert-info">
27160          *   Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
27161          *   This may be useful when, for instance, nesting ngRepeats.
27162          * </div>
27163          *
27164          *
27165          * # Iterating over object properties
27166          *
27167          * It is possible to get `ngRepeat` to iterate over the properties of an object using the following
27168          * syntax:
27169          *
27170          * ```js
27171          * <div ng-repeat="(key, value) in myObj"> ... </div>
27172          * ```
27173          *
27174          * You need to be aware that the JavaScript specification does not define the order of keys
27175          * returned for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive
27176          * used to sort the keys alphabetically.)
27177          *
27178          * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser
27179          * when running `for key in myObj`. It seems that browsers generally follow the strategy of providing
27180          * keys in the order in which they were defined, although there are exceptions when keys are deleted
27181          * and reinstated. See the [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).
27182          *
27183          * If this is not desired, the recommended workaround is to convert your object into an array
27184          * that is sorted into the order that you prefer before providing it to `ngRepeat`.  You could
27185          * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)
27186          * or implement a `$watch` on the object yourself.
27187          *
27188          *
27189          * # Tracking and Duplicates
27190          *
27191          * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in
27192          * the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:
27193          *
27194          * * When an item is added, a new instance of the template is added to the DOM.
27195          * * When an item is removed, its template instance is removed from the DOM.
27196          * * When items are reordered, their respective templates are reordered in the DOM.
27197          *
27198          * To minimize creation of DOM elements, `ngRepeat` uses a function
27199          * to "keep track" of all items in the collection and their corresponding DOM elements.
27200          * For example, if an item is added to the collection, ngRepeat will know that all other items
27201          * already have DOM elements, and will not re-render them.
27202          *
27203          * The default tracking function (which tracks items by their identity) does not allow
27204          * duplicate items in arrays. This is because when there are duplicates, it is not possible
27205          * to maintain a one-to-one mapping between collection items and DOM elements.
27206          *
27207          * If you do need to repeat duplicate items, you can substitute the default tracking behavior
27208          * with your own using the `track by` expression.
27209          *
27210          * For example, you may track items by the index of each item in the collection, using the
27211          * special scope property `$index`:
27212          * ```html
27213          *    <div ng-repeat="n in [42, 42, 43, 43] track by $index">
27214          *      {{n}}
27215          *    </div>
27216          * ```
27217          *
27218          * You may also use arbitrary expressions in `track by`, including references to custom functions
27219          * on the scope:
27220          * ```html
27221          *    <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
27222          *      {{n}}
27223          *    </div>
27224          * ```
27225          *
27226          * <div class="alert alert-success">
27227          * If you are working with objects that have an identifier property, you should track
27228          * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
27229          * will not have to rebuild the DOM elements for items it has already rendered, even if the
27230          * JavaScript objects in the collection have been substituted for new ones. For large collections,
27231          * this signifincantly improves rendering performance. If you don't have a unique identifier,
27232          * `track by $index` can also provide a performance boost.
27233          * </div>
27234          * ```html
27235          *    <div ng-repeat="model in collection track by model.id">
27236          *      {{model.name}}
27237          *    </div>
27238          * ```
27239          *
27240          * When no `track by` expression is provided, it is equivalent to tracking by the built-in
27241          * `$id` function, which tracks items by their identity:
27242          * ```html
27243          *    <div ng-repeat="obj in collection track by $id(obj)">
27244          *      {{obj.prop}}
27245          *    </div>
27246          * ```
27247          *
27248          * <div class="alert alert-warning">
27249          * **Note:** `track by` must always be the last expression:
27250          * </div>
27251          * ```
27252          * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
27253          *     {{model.name}}
27254          * </div>
27255          * ```
27256          *
27257          * # Special repeat start and end points
27258          * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
27259          * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
27260          * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
27261          * up to and including the ending HTML tag where **ng-repeat-end** is placed.
27262          *
27263          * The example below makes use of this feature:
27264          * ```html
27265          *   <header ng-repeat-start="item in items">
27266          *     Header {{ item }}
27267          *   </header>
27268          *   <div class="body">
27269          *     Body {{ item }}
27270          *   </div>
27271          *   <footer ng-repeat-end>
27272          *     Footer {{ item }}
27273          *   </footer>
27274          * ```
27275          *
27276          * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
27277          * ```html
27278          *   <header>
27279          *     Header A
27280          *   </header>
27281          *   <div class="body">
27282          *     Body A
27283          *   </div>
27284          *   <footer>
27285          *     Footer A
27286          *   </footer>
27287          *   <header>
27288          *     Header B
27289          *   </header>
27290          *   <div class="body">
27291          *     Body B
27292          *   </div>
27293          *   <footer>
27294          *     Footer B
27295          *   </footer>
27296          * ```
27297          *
27298          * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
27299          * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
27300          *
27301          * @animations
27302          * **.enter** - when a new item is added to the list or when an item is revealed after a filter
27303          *
27304          * **.leave** - when an item is removed from the list or when an item is filtered out
27305          *
27306          * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
27307          *
27308          * @element ANY
27309          * @scope
27310          * @priority 1000
27311          * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
27312          *   formats are currently supported:
27313          *
27314          *   * `variable in expression` – where variable is the user defined loop variable and `expression`
27315          *     is a scope expression giving the collection to enumerate.
27316          *
27317          *     For example: `album in artist.albums`.
27318          *
27319          *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
27320          *     and `expression` is the scope expression giving the collection to enumerate.
27321          *
27322          *     For example: `(name, age) in {'adam':10, 'amalie':12}`.
27323          *
27324          *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
27325          *     which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
27326          *     is specified, ng-repeat associates elements by identity. It is an error to have
27327          *     more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
27328          *     mapped to the same DOM element, which is not possible.)
27329          *
27330          *     Note that the tracking expression must come last, after any filters, and the alias expression.
27331          *
27332          *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
27333          *     will be associated by item identity in the array.
27334          *
27335          *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
27336          *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
27337          *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM
27338          *     element in the same way in the DOM.
27339          *
27340          *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
27341          *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`
27342          *     property is same.
27343          *
27344          *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
27345          *     to items in conjunction with a tracking expression.
27346          *
27347          *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
27348          *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
27349          *     when a filter is active on the repeater, but the filtered result set is empty.
27350          *
27351          *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
27352          *     the items have been processed through the filter.
27353          *
27354          *     Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end
27355          *     (and not as operator, inside an expression).
27356          *
27357          *     For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
27358          *
27359          * @example
27360          * This example initializes the scope to a list of names and
27361          * then uses `ngRepeat` to display every person:
27362           <example module="ngAnimate" deps="angular-animate.js" animations="true">
27363             <file name="index.html">
27364               <div ng-init="friends = [
27365                 {name:'John', age:25, gender:'boy'},
27366                 {name:'Jessie', age:30, gender:'girl'},
27367                 {name:'Johanna', age:28, gender:'girl'},
27368                 {name:'Joy', age:15, gender:'girl'},
27369                 {name:'Mary', age:28, gender:'girl'},
27370                 {name:'Peter', age:95, gender:'boy'},
27371                 {name:'Sebastian', age:50, gender:'boy'},
27372                 {name:'Erika', age:27, gender:'girl'},
27373                 {name:'Patrick', age:40, gender:'boy'},
27374                 {name:'Samantha', age:60, gender:'girl'}
27375               ]">
27376                 I have {{friends.length}} friends. They are:
27377                 <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
27378                 <ul class="example-animate-container">
27379                   <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
27380                     [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
27381                   </li>
27382                   <li class="animate-repeat" ng-if="results.length == 0">
27383                     <strong>No results found...</strong>
27384                   </li>
27385                 </ul>
27386               </div>
27387             </file>
27388             <file name="animations.css">
27389               .example-animate-container {
27390                 background:white;
27391                 border:1px solid black;
27392                 list-style:none;
27393                 margin:0;
27394                 padding:0 10px;
27395               }
27396
27397               .animate-repeat {
27398                 line-height:40px;
27399                 list-style:none;
27400                 box-sizing:border-box;
27401               }
27402
27403               .animate-repeat.ng-move,
27404               .animate-repeat.ng-enter,
27405               .animate-repeat.ng-leave {
27406                 transition:all linear 0.5s;
27407               }
27408
27409               .animate-repeat.ng-leave.ng-leave-active,
27410               .animate-repeat.ng-move,
27411               .animate-repeat.ng-enter {
27412                 opacity:0;
27413                 max-height:0;
27414               }
27415
27416               .animate-repeat.ng-leave,
27417               .animate-repeat.ng-move.ng-move-active,
27418               .animate-repeat.ng-enter.ng-enter-active {
27419                 opacity:1;
27420                 max-height:40px;
27421               }
27422             </file>
27423             <file name="protractor.js" type="protractor">
27424               var friends = element.all(by.repeater('friend in friends'));
27425
27426               it('should render initial data set', function() {
27427                 expect(friends.count()).toBe(10);
27428                 expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
27429                 expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
27430                 expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
27431                 expect(element(by.binding('friends.length')).getText())
27432                     .toMatch("I have 10 friends. They are:");
27433               });
27434
27435                it('should update repeater when filter predicate changes', function() {
27436                  expect(friends.count()).toBe(10);
27437
27438                  element(by.model('q')).sendKeys('ma');
27439
27440                  expect(friends.count()).toBe(2);
27441                  expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
27442                  expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
27443                });
27444               </file>
27445             </example>
27446          */
27447         var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
27448           var NG_REMOVED = '$$NG_REMOVED';
27449           var ngRepeatMinErr = minErr('ngRepeat');
27450
27451           var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {
27452             // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
27453             scope[valueIdentifier] = value;
27454             if (keyIdentifier) scope[keyIdentifier] = key;
27455             scope.$index = index;
27456             scope.$first = (index === 0);
27457             scope.$last = (index === (arrayLength - 1));
27458             scope.$middle = !(scope.$first || scope.$last);
27459             // jshint bitwise: false
27460             scope.$odd = !(scope.$even = (index&1) === 0);
27461             // jshint bitwise: true
27462           };
27463
27464           var getBlockStart = function(block) {
27465             return block.clone[0];
27466           };
27467
27468           var getBlockEnd = function(block) {
27469             return block.clone[block.clone.length - 1];
27470           };
27471
27472
27473           return {
27474             restrict: 'A',
27475             multiElement: true,
27476             transclude: 'element',
27477             priority: 1000,
27478             terminal: true,
27479             $$tlb: true,
27480             compile: function ngRepeatCompile($element, $attr) {
27481               var expression = $attr.ngRepeat;
27482               var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');
27483
27484               var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
27485
27486               if (!match) {
27487                 throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
27488                     expression);
27489               }
27490
27491               var lhs = match[1];
27492               var rhs = match[2];
27493               var aliasAs = match[3];
27494               var trackByExp = match[4];
27495
27496               match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
27497
27498               if (!match) {
27499                 throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
27500                     lhs);
27501               }
27502               var valueIdentifier = match[3] || match[1];
27503               var keyIdentifier = match[2];
27504
27505               if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
27506                   /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) {
27507                 throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
27508                   aliasAs);
27509               }
27510
27511               var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;
27512               var hashFnLocals = {$id: hashKey};
27513
27514               if (trackByExp) {
27515                 trackByExpGetter = $parse(trackByExp);
27516               } else {
27517                 trackByIdArrayFn = function(key, value) {
27518                   return hashKey(value);
27519                 };
27520                 trackByIdObjFn = function(key) {
27521                   return key;
27522                 };
27523               }
27524
27525               return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
27526
27527                 if (trackByExpGetter) {
27528                   trackByIdExpFn = function(key, value, index) {
27529                     // assign key, value, and $index to the locals so that they can be used in hash functions
27530                     if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
27531                     hashFnLocals[valueIdentifier] = value;
27532                     hashFnLocals.$index = index;
27533                     return trackByExpGetter($scope, hashFnLocals);
27534                   };
27535                 }
27536
27537                 // Store a list of elements from previous run. This is a hash where key is the item from the
27538                 // iterator, and the value is objects with following properties.
27539                 //   - scope: bound scope
27540                 //   - element: previous element.
27541                 //   - index: position
27542                 //
27543                 // We are using no-proto object so that we don't need to guard against inherited props via
27544                 // hasOwnProperty.
27545                 var lastBlockMap = createMap();
27546
27547                 //watch props
27548                 $scope.$watchCollection(rhs, function ngRepeatAction(collection) {
27549                   var index, length,
27550                       previousNode = $element[0],     // node that cloned nodes should be inserted after
27551                                                       // initialized to the comment node anchor
27552                       nextNode,
27553                       // Same as lastBlockMap but it has the current state. It will become the
27554                       // lastBlockMap on the next iteration.
27555                       nextBlockMap = createMap(),
27556                       collectionLength,
27557                       key, value, // key/value of iteration
27558                       trackById,
27559                       trackByIdFn,
27560                       collectionKeys,
27561                       block,       // last object information {scope, element, id}
27562                       nextBlockOrder,
27563                       elementsToRemove;
27564
27565                   if (aliasAs) {
27566                     $scope[aliasAs] = collection;
27567                   }
27568
27569                   if (isArrayLike(collection)) {
27570                     collectionKeys = collection;
27571                     trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
27572                   } else {
27573                     trackByIdFn = trackByIdExpFn || trackByIdObjFn;
27574                     // if object, extract keys, in enumeration order, unsorted
27575                     collectionKeys = [];
27576                     for (var itemKey in collection) {
27577                       if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {
27578                         collectionKeys.push(itemKey);
27579                       }
27580                     }
27581                   }
27582
27583                   collectionLength = collectionKeys.length;
27584                   nextBlockOrder = new Array(collectionLength);
27585
27586                   // locate existing items
27587                   for (index = 0; index < collectionLength; index++) {
27588                     key = (collection === collectionKeys) ? index : collectionKeys[index];
27589                     value = collection[key];
27590                     trackById = trackByIdFn(key, value, index);
27591                     if (lastBlockMap[trackById]) {
27592                       // found previously seen block
27593                       block = lastBlockMap[trackById];
27594                       delete lastBlockMap[trackById];
27595                       nextBlockMap[trackById] = block;
27596                       nextBlockOrder[index] = block;
27597                     } else if (nextBlockMap[trackById]) {
27598                       // if collision detected. restore lastBlockMap and throw an error
27599                       forEach(nextBlockOrder, function(block) {
27600                         if (block && block.scope) lastBlockMap[block.id] = block;
27601                       });
27602                       throw ngRepeatMinErr('dupes',
27603                           "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
27604                           expression, trackById, value);
27605                     } else {
27606                       // new never before seen block
27607                       nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
27608                       nextBlockMap[trackById] = true;
27609                     }
27610                   }
27611
27612                   // remove leftover items
27613                   for (var blockKey in lastBlockMap) {
27614                     block = lastBlockMap[blockKey];
27615                     elementsToRemove = getBlockNodes(block.clone);
27616                     $animate.leave(elementsToRemove);
27617                     if (elementsToRemove[0].parentNode) {
27618                       // if the element was not removed yet because of pending animation, mark it as deleted
27619                       // so that we can ignore it later
27620                       for (index = 0, length = elementsToRemove.length; index < length; index++) {
27621                         elementsToRemove[index][NG_REMOVED] = true;
27622                       }
27623                     }
27624                     block.scope.$destroy();
27625                   }
27626
27627                   // we are not using forEach for perf reasons (trying to avoid #call)
27628                   for (index = 0; index < collectionLength; index++) {
27629                     key = (collection === collectionKeys) ? index : collectionKeys[index];
27630                     value = collection[key];
27631                     block = nextBlockOrder[index];
27632
27633                     if (block.scope) {
27634                       // if we have already seen this object, then we need to reuse the
27635                       // associated scope/element
27636
27637                       nextNode = previousNode;
27638
27639                       // skip nodes that are already pending removal via leave animation
27640                       do {
27641                         nextNode = nextNode.nextSibling;
27642                       } while (nextNode && nextNode[NG_REMOVED]);
27643
27644                       if (getBlockStart(block) != nextNode) {
27645                         // existing item which got moved
27646                         $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
27647                       }
27648                       previousNode = getBlockEnd(block);
27649                       updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
27650                     } else {
27651                       // new item which we don't know about
27652                       $transclude(function ngRepeatTransclude(clone, scope) {
27653                         block.scope = scope;
27654                         // http://jsperf.com/clone-vs-createcomment
27655                         var endNode = ngRepeatEndComment.cloneNode(false);
27656                         clone[clone.length++] = endNode;
27657
27658                         // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?
27659                         $animate.enter(clone, null, jqLite(previousNode));
27660                         previousNode = endNode;
27661                         // Note: We only need the first/last node of the cloned nodes.
27662                         // However, we need to keep the reference to the jqlite wrapper as it might be changed later
27663                         // by a directive with templateUrl when its template arrives.
27664                         block.clone = clone;
27665                         nextBlockMap[block.id] = block;
27666                         updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
27667                       });
27668                     }
27669                   }
27670                   lastBlockMap = nextBlockMap;
27671                 });
27672               };
27673             }
27674           };
27675         }];
27676
27677         var NG_HIDE_CLASS = 'ng-hide';
27678         var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
27679         /**
27680          * @ngdoc directive
27681          * @name ngShow
27682          * @multiElement
27683          *
27684          * @description
27685          * The `ngShow` directive shows or hides the given HTML element based on the expression
27686          * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
27687          * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
27688          * in AngularJS and sets the display style to none (using an !important flag).
27689          * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
27690          *
27691          * ```html
27692          * <!-- when $scope.myValue is truthy (element is visible) -->
27693          * <div ng-show="myValue"></div>
27694          *
27695          * <!-- when $scope.myValue is falsy (element is hidden) -->
27696          * <div ng-show="myValue" class="ng-hide"></div>
27697          * ```
27698          *
27699          * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class
27700          * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed
27701          * from the element causing the element not to appear hidden.
27702          *
27703          * ## Why is !important used?
27704          *
27705          * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
27706          * can be easily overridden by heavier selectors. For example, something as simple
27707          * as changing the display style on a HTML list item would make hidden elements appear visible.
27708          * This also becomes a bigger issue when dealing with CSS frameworks.
27709          *
27710          * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
27711          * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
27712          * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
27713          *
27714          * ### Overriding `.ng-hide`
27715          *
27716          * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
27717          * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
27718          * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope
27719          * with extra animation classes that can be added.
27720          *
27721          * ```css
27722          * .ng-hide:not(.ng-hide-animate) {
27723          *   /&#42; this is just another form of hiding an element &#42;/
27724          *   display: block!important;
27725          *   position: absolute;
27726          *   top: -9999px;
27727          *   left: -9999px;
27728          * }
27729          * ```
27730          *
27731          * By default you don't need to override in CSS anything and the animations will work around the display style.
27732          *
27733          * ## A note about animations with `ngShow`
27734          *
27735          * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
27736          * is true and false. This system works like the animation system present with ngClass except that
27737          * you must also include the !important flag to override the display property
27738          * so that you can perform an animation when the element is hidden during the time of the animation.
27739          *
27740          * ```css
27741          * //
27742          * //a working example can be found at the bottom of this page
27743          * //
27744          * .my-element.ng-hide-add, .my-element.ng-hide-remove {
27745          *   /&#42; this is required as of 1.3x to properly
27746          *      apply all styling in a show/hide animation &#42;/
27747          *   transition: 0s linear all;
27748          * }
27749          *
27750          * .my-element.ng-hide-add-active,
27751          * .my-element.ng-hide-remove-active {
27752          *   /&#42; the transition is defined in the active class &#42;/
27753          *   transition: 1s linear all;
27754          * }
27755          *
27756          * .my-element.ng-hide-add { ... }
27757          * .my-element.ng-hide-add.ng-hide-add-active { ... }
27758          * .my-element.ng-hide-remove { ... }
27759          * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
27760          * ```
27761          *
27762          * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
27763          * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
27764          *
27765          * @animations
27766          * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
27767          * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
27768          *
27769          * @element ANY
27770          * @param {expression} ngShow If the {@link guide/expression expression} is truthy
27771          *     then the element is shown or hidden respectively.
27772          *
27773          * @example
27774           <example module="ngAnimate" deps="angular-animate.js" animations="true">
27775             <file name="index.html">
27776               Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngHide"><br/>
27777               <div>
27778                 Show:
27779                 <div class="check-element animate-show" ng-show="checked">
27780                   <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
27781                 </div>
27782               </div>
27783               <div>
27784                 Hide:
27785                 <div class="check-element animate-show" ng-hide="checked">
27786                   <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
27787                 </div>
27788               </div>
27789             </file>
27790             <file name="glyphicons.css">
27791               @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
27792             </file>
27793             <file name="animations.css">
27794               .animate-show {
27795                 line-height: 20px;
27796                 opacity: 1;
27797                 padding: 10px;
27798                 border: 1px solid black;
27799                 background: white;
27800               }
27801
27802               .animate-show.ng-hide-add, .animate-show.ng-hide-remove {
27803                 transition: all linear 0.5s;
27804               }
27805
27806               .animate-show.ng-hide {
27807                 line-height: 0;
27808                 opacity: 0;
27809                 padding: 0 10px;
27810               }
27811
27812               .check-element {
27813                 padding: 10px;
27814                 border: 1px solid black;
27815                 background: white;
27816               }
27817             </file>
27818             <file name="protractor.js" type="protractor">
27819               var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
27820               var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
27821
27822               it('should check ng-show / ng-hide', function() {
27823                 expect(thumbsUp.isDisplayed()).toBeFalsy();
27824                 expect(thumbsDown.isDisplayed()).toBeTruthy();
27825
27826                 element(by.model('checked')).click();
27827
27828                 expect(thumbsUp.isDisplayed()).toBeTruthy();
27829                 expect(thumbsDown.isDisplayed()).toBeFalsy();
27830               });
27831             </file>
27832           </example>
27833          */
27834         var ngShowDirective = ['$animate', function($animate) {
27835           return {
27836             restrict: 'A',
27837             multiElement: true,
27838             link: function(scope, element, attr) {
27839               scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
27840                 // we're adding a temporary, animation-specific class for ng-hide since this way
27841                 // we can control when the element is actually displayed on screen without having
27842                 // to have a global/greedy CSS selector that breaks when other animations are run.
27843                 // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
27844                 $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
27845                   tempClasses: NG_HIDE_IN_PROGRESS_CLASS
27846                 });
27847               });
27848             }
27849           };
27850         }];
27851
27852
27853         /**
27854          * @ngdoc directive
27855          * @name ngHide
27856          * @multiElement
27857          *
27858          * @description
27859          * The `ngHide` directive shows or hides the given HTML element based on the expression
27860          * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
27861          * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
27862          * in AngularJS and sets the display style to none (using an !important flag).
27863          * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
27864          *
27865          * ```html
27866          * <!-- when $scope.myValue is truthy (element is hidden) -->
27867          * <div ng-hide="myValue" class="ng-hide"></div>
27868          *
27869          * <!-- when $scope.myValue is falsy (element is visible) -->
27870          * <div ng-hide="myValue"></div>
27871          * ```
27872          *
27873          * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class
27874          * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed
27875          * from the element causing the element not to appear hidden.
27876          *
27877          * ## Why is !important used?
27878          *
27879          * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
27880          * can be easily overridden by heavier selectors. For example, something as simple
27881          * as changing the display style on a HTML list item would make hidden elements appear visible.
27882          * This also becomes a bigger issue when dealing with CSS frameworks.
27883          *
27884          * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
27885          * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
27886          * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
27887          *
27888          * ### Overriding `.ng-hide`
27889          *
27890          * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
27891          * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
27892          * class in CSS:
27893          *
27894          * ```css
27895          * .ng-hide {
27896          *   /&#42; this is just another form of hiding an element &#42;/
27897          *   display: block!important;
27898          *   position: absolute;
27899          *   top: -9999px;
27900          *   left: -9999px;
27901          * }
27902          * ```
27903          *
27904          * By default you don't need to override in CSS anything and the animations will work around the display style.
27905          *
27906          * ## A note about animations with `ngHide`
27907          *
27908          * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
27909          * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
27910          * CSS class is added and removed for you instead of your own CSS class.
27911          *
27912          * ```css
27913          * //
27914          * //a working example can be found at the bottom of this page
27915          * //
27916          * .my-element.ng-hide-add, .my-element.ng-hide-remove {
27917          *   transition: 0.5s linear all;
27918          * }
27919          *
27920          * .my-element.ng-hide-add { ... }
27921          * .my-element.ng-hide-add.ng-hide-add-active { ... }
27922          * .my-element.ng-hide-remove { ... }
27923          * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
27924          * ```
27925          *
27926          * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
27927          * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
27928          *
27929          * @animations
27930          * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
27931          * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
27932          *
27933          * @element ANY
27934          * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
27935          *     the element is shown or hidden respectively.
27936          *
27937          * @example
27938           <example module="ngAnimate" deps="angular-animate.js" animations="true">
27939             <file name="index.html">
27940               Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow"><br/>
27941               <div>
27942                 Show:
27943                 <div class="check-element animate-hide" ng-show="checked">
27944                   <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
27945                 </div>
27946               </div>
27947               <div>
27948                 Hide:
27949                 <div class="check-element animate-hide" ng-hide="checked">
27950                   <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
27951                 </div>
27952               </div>
27953             </file>
27954             <file name="glyphicons.css">
27955               @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
27956             </file>
27957             <file name="animations.css">
27958               .animate-hide {
27959                 transition: all linear 0.5s;
27960                 line-height: 20px;
27961                 opacity: 1;
27962                 padding: 10px;
27963                 border: 1px solid black;
27964                 background: white;
27965               }
27966
27967               .animate-hide.ng-hide {
27968                 line-height: 0;
27969                 opacity: 0;
27970                 padding: 0 10px;
27971               }
27972
27973               .check-element {
27974                 padding: 10px;
27975                 border: 1px solid black;
27976                 background: white;
27977               }
27978             </file>
27979             <file name="protractor.js" type="protractor">
27980               var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
27981               var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
27982
27983               it('should check ng-show / ng-hide', function() {
27984                 expect(thumbsUp.isDisplayed()).toBeFalsy();
27985                 expect(thumbsDown.isDisplayed()).toBeTruthy();
27986
27987                 element(by.model('checked')).click();
27988
27989                 expect(thumbsUp.isDisplayed()).toBeTruthy();
27990                 expect(thumbsDown.isDisplayed()).toBeFalsy();
27991               });
27992             </file>
27993           </example>
27994          */
27995         var ngHideDirective = ['$animate', function($animate) {
27996           return {
27997             restrict: 'A',
27998             multiElement: true,
27999             link: function(scope, element, attr) {
28000               scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
28001                 // The comment inside of the ngShowDirective explains why we add and
28002                 // remove a temporary class for the show/hide animation
28003                 $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
28004                   tempClasses: NG_HIDE_IN_PROGRESS_CLASS
28005                 });
28006               });
28007             }
28008           };
28009         }];
28010
28011         /**
28012          * @ngdoc directive
28013          * @name ngStyle
28014          * @restrict AC
28015          *
28016          * @description
28017          * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
28018          *
28019          * @element ANY
28020          * @param {expression} ngStyle
28021          *
28022          * {@link guide/expression Expression} which evals to an
28023          * object whose keys are CSS style names and values are corresponding values for those CSS
28024          * keys.
28025          *
28026          * Since some CSS style names are not valid keys for an object, they must be quoted.
28027          * See the 'background-color' style in the example below.
28028          *
28029          * @example
28030            <example>
28031              <file name="index.html">
28032                 <input type="button" value="set color" ng-click="myStyle={color:'red'}">
28033                 <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
28034                 <input type="button" value="clear" ng-click="myStyle={}">
28035                 <br/>
28036                 <span ng-style="myStyle">Sample Text</span>
28037                 <pre>myStyle={{myStyle}}</pre>
28038              </file>
28039              <file name="style.css">
28040                span {
28041                  color: black;
28042                }
28043              </file>
28044              <file name="protractor.js" type="protractor">
28045                var colorSpan = element(by.css('span'));
28046
28047                it('should check ng-style', function() {
28048                  expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
28049                  element(by.css('input[value=\'set color\']')).click();
28050                  expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
28051                  element(by.css('input[value=clear]')).click();
28052                  expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
28053                });
28054              </file>
28055            </example>
28056          */
28057         var ngStyleDirective = ngDirective(function(scope, element, attr) {
28058           scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
28059             if (oldStyles && (newStyles !== oldStyles)) {
28060               forEach(oldStyles, function(val, style) { element.css(style, '');});
28061             }
28062             if (newStyles) element.css(newStyles);
28063           }, true);
28064         });
28065
28066         /**
28067          * @ngdoc directive
28068          * @name ngSwitch
28069          * @restrict EA
28070          *
28071          * @description
28072          * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
28073          * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
28074          * as specified in the template.
28075          *
28076          * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
28077          * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
28078          * matches the value obtained from the evaluated expression. In other words, you define a container element
28079          * (where you place the directive), place an expression on the **`on="..."` attribute**
28080          * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
28081          * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
28082          * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
28083          * attribute is displayed.
28084          *
28085          * <div class="alert alert-info">
28086          * Be aware that the attribute values to match against cannot be expressions. They are interpreted
28087          * as literal string values to match against.
28088          * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
28089          * value of the expression `$scope.someVal`.
28090          * </div>
28091
28092          * @animations
28093          * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
28094          * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
28095          *
28096          * @usage
28097          *
28098          * ```
28099          * <ANY ng-switch="expression">
28100          *   <ANY ng-switch-when="matchValue1">...</ANY>
28101          *   <ANY ng-switch-when="matchValue2">...</ANY>
28102          *   <ANY ng-switch-default>...</ANY>
28103          * </ANY>
28104          * ```
28105          *
28106          *
28107          * @scope
28108          * @priority 1200
28109          * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
28110          * On child elements add:
28111          *
28112          * * `ngSwitchWhen`: the case statement to match against. If match then this
28113          *   case will be displayed. If the same match appears multiple times, all the
28114          *   elements will be displayed.
28115          * * `ngSwitchDefault`: the default case when no other case match. If there
28116          *   are multiple default cases, all of them will be displayed when no other
28117          *   case match.
28118          *
28119          *
28120          * @example
28121           <example module="switchExample" deps="angular-animate.js" animations="true">
28122             <file name="index.html">
28123               <div ng-controller="ExampleController">
28124                 <select ng-model="selection" ng-options="item for item in items">
28125                 </select>
28126                 <code>selection={{selection}}</code>
28127                 <hr/>
28128                 <div class="animate-switch-container"
28129                   ng-switch on="selection">
28130                     <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
28131                     <div class="animate-switch" ng-switch-when="home">Home Span</div>
28132                     <div class="animate-switch" ng-switch-default>default</div>
28133                 </div>
28134               </div>
28135             </file>
28136             <file name="script.js">
28137               angular.module('switchExample', ['ngAnimate'])
28138                 .controller('ExampleController', ['$scope', function($scope) {
28139                   $scope.items = ['settings', 'home', 'other'];
28140                   $scope.selection = $scope.items[0];
28141                 }]);
28142             </file>
28143             <file name="animations.css">
28144               .animate-switch-container {
28145                 position:relative;
28146                 background:white;
28147                 border:1px solid black;
28148                 height:40px;
28149                 overflow:hidden;
28150               }
28151
28152               .animate-switch {
28153                 padding:10px;
28154               }
28155
28156               .animate-switch.ng-animate {
28157                 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
28158
28159                 position:absolute;
28160                 top:0;
28161                 left:0;
28162                 right:0;
28163                 bottom:0;
28164               }
28165
28166               .animate-switch.ng-leave.ng-leave-active,
28167               .animate-switch.ng-enter {
28168                 top:-50px;
28169               }
28170               .animate-switch.ng-leave,
28171               .animate-switch.ng-enter.ng-enter-active {
28172                 top:0;
28173               }
28174             </file>
28175             <file name="protractor.js" type="protractor">
28176               var switchElem = element(by.css('[ng-switch]'));
28177               var select = element(by.model('selection'));
28178
28179               it('should start in settings', function() {
28180                 expect(switchElem.getText()).toMatch(/Settings Div/);
28181               });
28182               it('should change to home', function() {
28183                 select.all(by.css('option')).get(1).click();
28184                 expect(switchElem.getText()).toMatch(/Home Span/);
28185               });
28186               it('should select default', function() {
28187                 select.all(by.css('option')).get(2).click();
28188                 expect(switchElem.getText()).toMatch(/default/);
28189               });
28190             </file>
28191           </example>
28192          */
28193         var ngSwitchDirective = ['$animate', function($animate) {
28194           return {
28195             require: 'ngSwitch',
28196
28197             // asks for $scope to fool the BC controller module
28198             controller: ['$scope', function ngSwitchController() {
28199              this.cases = {};
28200             }],
28201             link: function(scope, element, attr, ngSwitchController) {
28202               var watchExpr = attr.ngSwitch || attr.on,
28203                   selectedTranscludes = [],
28204                   selectedElements = [],
28205                   previousLeaveAnimations = [],
28206                   selectedScopes = [];
28207
28208               var spliceFactory = function(array, index) {
28209                   return function() { array.splice(index, 1); };
28210               };
28211
28212               scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
28213                 var i, ii;
28214                 for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {
28215                   $animate.cancel(previousLeaveAnimations[i]);
28216                 }
28217                 previousLeaveAnimations.length = 0;
28218
28219                 for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
28220                   var selected = getBlockNodes(selectedElements[i].clone);
28221                   selectedScopes[i].$destroy();
28222                   var promise = previousLeaveAnimations[i] = $animate.leave(selected);
28223                   promise.then(spliceFactory(previousLeaveAnimations, i));
28224                 }
28225
28226                 selectedElements.length = 0;
28227                 selectedScopes.length = 0;
28228
28229                 if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
28230                   forEach(selectedTranscludes, function(selectedTransclude) {
28231                     selectedTransclude.transclude(function(caseElement, selectedScope) {
28232                       selectedScopes.push(selectedScope);
28233                       var anchor = selectedTransclude.element;
28234                       caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');
28235                       var block = { clone: caseElement };
28236
28237                       selectedElements.push(block);
28238                       $animate.enter(caseElement, anchor.parent(), anchor);
28239                     });
28240                   });
28241                 }
28242               });
28243             }
28244           };
28245         }];
28246
28247         var ngSwitchWhenDirective = ngDirective({
28248           transclude: 'element',
28249           priority: 1200,
28250           require: '^ngSwitch',
28251           multiElement: true,
28252           link: function(scope, element, attrs, ctrl, $transclude) {
28253             ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
28254             ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
28255           }
28256         });
28257
28258         var ngSwitchDefaultDirective = ngDirective({
28259           transclude: 'element',
28260           priority: 1200,
28261           require: '^ngSwitch',
28262           multiElement: true,
28263           link: function(scope, element, attr, ctrl, $transclude) {
28264             ctrl.cases['?'] = (ctrl.cases['?'] || []);
28265             ctrl.cases['?'].push({ transclude: $transclude, element: element });
28266            }
28267         });
28268
28269         /**
28270          * @ngdoc directive
28271          * @name ngTransclude
28272          * @restrict EAC
28273          *
28274          * @description
28275          * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
28276          *
28277          * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
28278          *
28279          * @element ANY
28280          *
28281          * @example
28282            <example module="transcludeExample">
28283              <file name="index.html">
28284                <script>
28285                  angular.module('transcludeExample', [])
28286                   .directive('pane', function(){
28287                      return {
28288                        restrict: 'E',
28289                        transclude: true,
28290                        scope: { title:'@' },
28291                        template: '<div style="border: 1px solid black;">' +
28292                                    '<div style="background-color: gray">{{title}}</div>' +
28293                                    '<ng-transclude></ng-transclude>' +
28294                                  '</div>'
28295                      };
28296                  })
28297                  .controller('ExampleController', ['$scope', function($scope) {
28298                    $scope.title = 'Lorem Ipsum';
28299                    $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
28300                  }]);
28301                </script>
28302                <div ng-controller="ExampleController">
28303                  <input ng-model="title" aria-label="title"> <br/>
28304                  <textarea ng-model="text" aria-label="text"></textarea> <br/>
28305                  <pane title="{{title}}">{{text}}</pane>
28306                </div>
28307              </file>
28308              <file name="protractor.js" type="protractor">
28309                 it('should have transcluded', function() {
28310                   var titleElement = element(by.model('title'));
28311                   titleElement.clear();
28312                   titleElement.sendKeys('TITLE');
28313                   var textElement = element(by.model('text'));
28314                   textElement.clear();
28315                   textElement.sendKeys('TEXT');
28316                   expect(element(by.binding('title')).getText()).toEqual('TITLE');
28317                   expect(element(by.binding('text')).getText()).toEqual('TEXT');
28318                 });
28319              </file>
28320            </example>
28321          *
28322          */
28323         var ngTranscludeDirective = ngDirective({
28324           restrict: 'EAC',
28325           link: function($scope, $element, $attrs, controller, $transclude) {
28326             if (!$transclude) {
28327               throw minErr('ngTransclude')('orphan',
28328                'Illegal use of ngTransclude directive in the template! ' +
28329                'No parent directive that requires a transclusion found. ' +
28330                'Element: {0}',
28331                startingTag($element));
28332             }
28333
28334             $transclude(function(clone) {
28335               $element.empty();
28336               $element.append(clone);
28337             });
28338           }
28339         });
28340
28341         /**
28342          * @ngdoc directive
28343          * @name script
28344          * @restrict E
28345          *
28346          * @description
28347          * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
28348          * template can be used by {@link ng.directive:ngInclude `ngInclude`},
28349          * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
28350          * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
28351          * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
28352          *
28353          * @param {string} type Must be set to `'text/ng-template'`.
28354          * @param {string} id Cache name of the template.
28355          *
28356          * @example
28357           <example>
28358             <file name="index.html">
28359               <script type="text/ng-template" id="/tpl.html">
28360                 Content of the template.
28361               </script>
28362
28363               <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
28364               <div id="tpl-content" ng-include src="currentTpl"></div>
28365             </file>
28366             <file name="protractor.js" type="protractor">
28367               it('should load template defined inside script tag', function() {
28368                 element(by.css('#tpl-link')).click();
28369                 expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
28370               });
28371             </file>
28372           </example>
28373          */
28374         var scriptDirective = ['$templateCache', function($templateCache) {
28375           return {
28376             restrict: 'E',
28377             terminal: true,
28378             compile: function(element, attr) {
28379               if (attr.type == 'text/ng-template') {
28380                 var templateUrl = attr.id,
28381                     text = element[0].text;
28382
28383                 $templateCache.put(templateUrl, text);
28384               }
28385             }
28386           };
28387         }];
28388
28389         var noopNgModelController = { $setViewValue: noop, $render: noop };
28390
28391         function chromeHack(optionElement) {
28392           // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
28393           // Adding an <option selected="selected"> element to a <select required="required"> should
28394           // automatically select the new element
28395           if (optionElement[0].hasAttribute('selected')) {
28396             optionElement[0].selected = true;
28397           }
28398         }
28399
28400         /**
28401          * @ngdoc type
28402          * @name  select.SelectController
28403          * @description
28404          * The controller for the `<select>` directive. This provides support for reading
28405          * and writing the selected value(s) of the control and also coordinates dynamically
28406          * added `<option>` elements, perhaps by an `ngRepeat` directive.
28407          */
28408         var SelectController =
28409                 ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
28410
28411           var self = this,
28412               optionsMap = new HashMap();
28413
28414           // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors
28415           self.ngModelCtrl = noopNgModelController;
28416
28417           // The "unknown" option is one that is prepended to the list if the viewValue
28418           // does not match any of the options. When it is rendered the value of the unknown
28419           // option is '? XXX ?' where XXX is the hashKey of the value that is not known.
28420           //
28421           // We can't just jqLite('<option>') since jqLite is not smart enough
28422           // to create it in <select> and IE barfs otherwise.
28423           self.unknownOption = jqLite(document.createElement('option'));
28424           self.renderUnknownOption = function(val) {
28425             var unknownVal = '? ' + hashKey(val) + ' ?';
28426             self.unknownOption.val(unknownVal);
28427             $element.prepend(self.unknownOption);
28428             $element.val(unknownVal);
28429           };
28430
28431           $scope.$on('$destroy', function() {
28432             // disable unknown option so that we don't do work when the whole select is being destroyed
28433             self.renderUnknownOption = noop;
28434           });
28435
28436           self.removeUnknownOption = function() {
28437             if (self.unknownOption.parent()) self.unknownOption.remove();
28438           };
28439
28440
28441           // Read the value of the select control, the implementation of this changes depending
28442           // upon whether the select can have multiple values and whether ngOptions is at work.
28443           self.readValue = function readSingleValue() {
28444             self.removeUnknownOption();
28445             return $element.val();
28446           };
28447
28448
28449           // Write the value to the select control, the implementation of this changes depending
28450           // upon whether the select can have multiple values and whether ngOptions is at work.
28451           self.writeValue = function writeSingleValue(value) {
28452             if (self.hasOption(value)) {
28453               self.removeUnknownOption();
28454               $element.val(value);
28455               if (value === '') self.emptyOption.prop('selected', true); // to make IE9 happy
28456             } else {
28457               if (value == null && self.emptyOption) {
28458                 self.removeUnknownOption();
28459                 $element.val('');
28460               } else {
28461                 self.renderUnknownOption(value);
28462               }
28463             }
28464           };
28465
28466
28467           // Tell the select control that an option, with the given value, has been added
28468           self.addOption = function(value, element) {
28469             assertNotHasOwnProperty(value, '"option value"');
28470             if (value === '') {
28471               self.emptyOption = element;
28472             }
28473             var count = optionsMap.get(value) || 0;
28474             optionsMap.put(value, count + 1);
28475             self.ngModelCtrl.$render();
28476             chromeHack(element);
28477           };
28478
28479           // Tell the select control that an option, with the given value, has been removed
28480           self.removeOption = function(value) {
28481             var count = optionsMap.get(value);
28482             if (count) {
28483               if (count === 1) {
28484                 optionsMap.remove(value);
28485                 if (value === '') {
28486                   self.emptyOption = undefined;
28487                 }
28488               } else {
28489                 optionsMap.put(value, count - 1);
28490               }
28491             }
28492           };
28493
28494           // Check whether the select control has an option matching the given value
28495           self.hasOption = function(value) {
28496             return !!optionsMap.get(value);
28497           };
28498
28499
28500           self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {
28501
28502             if (interpolateValueFn) {
28503               // The value attribute is interpolated
28504               var oldVal;
28505               optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) {
28506                 if (isDefined(oldVal)) {
28507                   self.removeOption(oldVal);
28508                 }
28509                 oldVal = newVal;
28510                 self.addOption(newVal, optionElement);
28511               });
28512             } else if (interpolateTextFn) {
28513               // The text content is interpolated
28514               optionScope.$watch(interpolateTextFn, function interpolateWatchAction(newVal, oldVal) {
28515                 optionAttrs.$set('value', newVal);
28516                 if (oldVal !== newVal) {
28517                   self.removeOption(oldVal);
28518                 }
28519                 self.addOption(newVal, optionElement);
28520               });
28521             } else {
28522               // The value attribute is static
28523               self.addOption(optionAttrs.value, optionElement);
28524             }
28525
28526             optionElement.on('$destroy', function() {
28527               self.removeOption(optionAttrs.value);
28528               self.ngModelCtrl.$render();
28529             });
28530           };
28531         }];
28532
28533         /**
28534          * @ngdoc directive
28535          * @name select
28536          * @restrict E
28537          *
28538          * @description
28539          * HTML `SELECT` element with angular data-binding.
28540          *
28541          * The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
28542          * between the scope and the `<select>` control (including setting default values).
28543          * Ìt also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
28544          * {@link ngOptions `ngOptions`} directives.
28545          *
28546          * When an item in the `<select>` menu is selected, the value of the selected option will be bound
28547          * to the model identified by the `ngModel` directive. With static or repeated options, this is
28548          * the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
28549          * If you want dynamic value attributes, you can use interpolation inside the value attribute.
28550          *
28551          * <div class="alert alert-warning">
28552          * Note that the value of a `select` directive used without `ngOptions` is always a string.
28553          * When the model needs to be bound to a non-string value, you must either explictly convert it
28554          * using a directive (see example below) or use `ngOptions` to specify the set of options.
28555          * This is because an option element can only be bound to string values at present.
28556          * </div>
28557          *
28558          * If the viewValue of `ngModel` does not match any of the options, then the control
28559          * will automatically add an "unknown" option, which it then removes when the mismatch is resolved.
28560          *
28561          * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
28562          * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
28563          * option. See example below for demonstration.
28564          *
28565          * <div class="alert alert-info">
28566          * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
28567          * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits, such as
28568          * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
28569          * comprehension expression, and additionally in reducing memory and increasing speed by not creating
28570          * a new scope for each repeated instance.
28571          * </div>
28572          *
28573          *
28574          * @param {string} ngModel Assignable angular expression to data-bind to.
28575          * @param {string=} name Property name of the form under which the control is published.
28576          * @param {string=} multiple Allows multiple options to be selected. The selected values will be
28577          *     bound to the model as an array.
28578          * @param {string=} required Sets `required` validation error key if the value is not entered.
28579          * @param {string=} ngRequired Adds required attribute and required validation constraint to
28580          * the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
28581          * when you want to data-bind to the required attribute.
28582          * @param {string=} ngChange Angular expression to be executed when selected option(s) changes due to user
28583          *    interaction with the select element.
28584          * @param {string=} ngOptions sets the options that the select is populated with and defines what is
28585          * set on the model on selection. See {@link ngOptions `ngOptions`}.
28586          *
28587          * @example
28588          * ### Simple `select` elements with static options
28589          *
28590          * <example name="static-select" module="staticSelect">
28591          * <file name="index.html">
28592          * <div ng-controller="ExampleController">
28593          *   <form name="myForm">
28594          *     <label for="singleSelect"> Single select: </label><br>
28595          *     <select name="singleSelect" ng-model="data.singleSelect">
28596          *       <option value="option-1">Option 1</option>
28597          *       <option value="option-2">Option 2</option>
28598          *     </select><br>
28599          *
28600          *     <label for="singleSelect"> Single select with "not selected" option and dynamic option values: </label><br>
28601          *     <select name="singleSelect" id="singleSelect" ng-model="data.singleSelect">
28602          *       <option value="">---Please select---</option> <!-- not selected / blank option -->
28603          *       <option value="{{data.option1}}">Option 1</option> <!-- interpolation -->
28604          *       <option value="option-2">Option 2</option>
28605          *     </select><br>
28606          *     <button ng-click="forceUnknownOption()">Force unknown option</button><br>
28607          *     <tt>singleSelect = {{data.singleSelect}}</tt>
28608          *
28609          *     <hr>
28610          *     <label for="multipleSelect"> Multiple select: </label><br>
28611          *     <select name="multipleSelect" id="multipleSelect" ng-model="data.multipleSelect" multiple>
28612          *       <option value="option-1">Option 1</option>
28613          *       <option value="option-2">Option 2</option>
28614          *       <option value="option-3">Option 3</option>
28615          *     </select><br>
28616          *     <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>
28617          *   </form>
28618          * </div>
28619          * </file>
28620          * <file name="app.js">
28621          *  angular.module('staticSelect', [])
28622          *    .controller('ExampleController', ['$scope', function($scope) {
28623          *      $scope.data = {
28624          *       singleSelect: null,
28625          *       multipleSelect: [],
28626          *       option1: 'option-1',
28627          *      };
28628          *
28629          *      $scope.forceUnknownOption = function() {
28630          *        $scope.data.singleSelect = 'nonsense';
28631          *      };
28632          *   }]);
28633          * </file>
28634          *</example>
28635          *
28636          * ### Using `ngRepeat` to generate `select` options
28637          * <example name="ngrepeat-select" module="ngrepeatSelect">
28638          * <file name="index.html">
28639          * <div ng-controller="ExampleController">
28640          *   <form name="myForm">
28641          *     <label for="repeatSelect"> Repeat select: </label>
28642          *     <select name="repeatSelect" id="repeatSelect" ng-model="data.repeatSelect">
28643          *       <option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
28644          *     </select>
28645          *   </form>
28646          *   <hr>
28647          *   <tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
28648          * </div>
28649          * </file>
28650          * <file name="app.js">
28651          *  angular.module('ngrepeatSelect', [])
28652          *    .controller('ExampleController', ['$scope', function($scope) {
28653          *      $scope.data = {
28654          *       repeatSelect: null,
28655          *       availableOptions: [
28656          *         {id: '1', name: 'Option A'},
28657          *         {id: '2', name: 'Option B'},
28658          *         {id: '3', name: 'Option C'}
28659          *       ],
28660          *      };
28661          *   }]);
28662          * </file>
28663          *</example>
28664          *
28665          *
28666          * ### Using `select` with `ngOptions` and setting a default value
28667          * See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.
28668          *
28669          * <example name="select-with-default-values" module="defaultValueSelect">
28670          * <file name="index.html">
28671          * <div ng-controller="ExampleController">
28672          *   <form name="myForm">
28673          *     <label for="mySelect">Make a choice:</label>
28674          *     <select name="mySelect" id="mySelect"
28675          *       ng-options="option.name for option in data.availableOptions track by option.id"
28676          *       ng-model="data.selectedOption"></select>
28677          *   </form>
28678          *   <hr>
28679          *   <tt>option = {{data.selectedOption}}</tt><br/>
28680          * </div>
28681          * </file>
28682          * <file name="app.js">
28683          *  angular.module('defaultValueSelect', [])
28684          *    .controller('ExampleController', ['$scope', function($scope) {
28685          *      $scope.data = {
28686          *       availableOptions: [
28687          *         {id: '1', name: 'Option A'},
28688          *         {id: '2', name: 'Option B'},
28689          *         {id: '3', name: 'Option C'}
28690          *       ],
28691          *       selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
28692          *       };
28693          *   }]);
28694          * </file>
28695          *</example>
28696          *
28697          *
28698          * ### Binding `select` to a non-string value via `ngModel` parsing / formatting
28699          *
28700          * <example name="select-with-non-string-options" module="nonStringSelect">
28701          *   <file name="index.html">
28702          *     <select ng-model="model.id" convert-to-number>
28703          *       <option value="0">Zero</option>
28704          *       <option value="1">One</option>
28705          *       <option value="2">Two</option>
28706          *     </select>
28707          *     {{ model }}
28708          *   </file>
28709          *   <file name="app.js">
28710          *     angular.module('nonStringSelect', [])
28711          *       .run(function($rootScope) {
28712          *         $rootScope.model = { id: 2 };
28713          *       })
28714          *       .directive('convertToNumber', function() {
28715          *         return {
28716          *           require: 'ngModel',
28717          *           link: function(scope, element, attrs, ngModel) {
28718          *             ngModel.$parsers.push(function(val) {
28719          *               return parseInt(val, 10);
28720          *             });
28721          *             ngModel.$formatters.push(function(val) {
28722          *               return '' + val;
28723          *             });
28724          *           }
28725          *         };
28726          *       });
28727          *   </file>
28728          *   <file name="protractor.js" type="protractor">
28729          *     it('should initialize to model', function() {
28730          *       var select = element(by.css('select'));
28731          *       expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two');
28732          *     });
28733          *   </file>
28734          * </example>
28735          *
28736          */
28737         var selectDirective = function() {
28738
28739           return {
28740             restrict: 'E',
28741             require: ['select', '?ngModel'],
28742             controller: SelectController,
28743             priority: 1,
28744             link: {
28745               pre: selectPreLink
28746             }
28747           };
28748
28749           function selectPreLink(scope, element, attr, ctrls) {
28750
28751               // if ngModel is not defined, we don't need to do anything
28752               var ngModelCtrl = ctrls[1];
28753               if (!ngModelCtrl) return;
28754
28755               var selectCtrl = ctrls[0];
28756
28757               selectCtrl.ngModelCtrl = ngModelCtrl;
28758
28759               // We delegate rendering to the `writeValue` method, which can be changed
28760               // if the select can have multiple selected values or if the options are being
28761               // generated by `ngOptions`
28762               ngModelCtrl.$render = function() {
28763                 selectCtrl.writeValue(ngModelCtrl.$viewValue);
28764               };
28765
28766               // When the selected item(s) changes we delegate getting the value of the select control
28767               // to the `readValue` method, which can be changed if the select can have multiple
28768               // selected values or if the options are being generated by `ngOptions`
28769               element.on('change', function() {
28770                 scope.$apply(function() {
28771                   ngModelCtrl.$setViewValue(selectCtrl.readValue());
28772                 });
28773               });
28774
28775               // If the select allows multiple values then we need to modify how we read and write
28776               // values from and to the control; also what it means for the value to be empty and
28777               // we have to add an extra watch since ngModel doesn't work well with arrays - it
28778               // doesn't trigger rendering if only an item in the array changes.
28779               if (attr.multiple) {
28780
28781                 // Read value now needs to check each option to see if it is selected
28782                 selectCtrl.readValue = function readMultipleValue() {
28783                   var array = [];
28784                   forEach(element.find('option'), function(option) {
28785                     if (option.selected) {
28786                       array.push(option.value);
28787                     }
28788                   });
28789                   return array;
28790                 };
28791
28792                 // Write value now needs to set the selected property of each matching option
28793                 selectCtrl.writeValue = function writeMultipleValue(value) {
28794                   var items = new HashMap(value);
28795                   forEach(element.find('option'), function(option) {
28796                     option.selected = isDefined(items.get(option.value));
28797                   });
28798                 };
28799
28800                 // we have to do it on each watch since ngModel watches reference, but
28801                 // we need to work of an array, so we need to see if anything was inserted/removed
28802                 var lastView, lastViewRef = NaN;
28803                 scope.$watch(function selectMultipleWatch() {
28804                   if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) {
28805                     lastView = shallowCopy(ngModelCtrl.$viewValue);
28806                     ngModelCtrl.$render();
28807                   }
28808                   lastViewRef = ngModelCtrl.$viewValue;
28809                 });
28810
28811                 // If we are a multiple select then value is now a collection
28812                 // so the meaning of $isEmpty changes
28813                 ngModelCtrl.$isEmpty = function(value) {
28814                   return !value || value.length === 0;
28815                 };
28816
28817               }
28818             }
28819         };
28820
28821
28822         // The option directive is purely designed to communicate the existence (or lack of)
28823         // of dynamically created (and destroyed) option elements to their containing select
28824         // directive via its controller.
28825         var optionDirective = ['$interpolate', function($interpolate) {
28826           return {
28827             restrict: 'E',
28828             priority: 100,
28829             compile: function(element, attr) {
28830
28831               if (isDefined(attr.value)) {
28832                 // If the value attribute is defined, check if it contains an interpolation
28833                 var interpolateValueFn = $interpolate(attr.value, true);
28834               } else {
28835                 // If the value attribute is not defined then we fall back to the
28836                 // text content of the option element, which may be interpolated
28837                 var interpolateTextFn = $interpolate(element.text(), true);
28838                 if (!interpolateTextFn) {
28839                   attr.$set('value', element.text());
28840                 }
28841               }
28842
28843               return function(scope, element, attr) {
28844
28845                 // This is an optimization over using ^^ since we don't want to have to search
28846                 // all the way to the root of the DOM for every single option element
28847                 var selectCtrlName = '$selectController',
28848                     parent = element.parent(),
28849                     selectCtrl = parent.data(selectCtrlName) ||
28850                       parent.parent().data(selectCtrlName); // in case we are in optgroup
28851
28852                 if (selectCtrl) {
28853                   selectCtrl.registerOption(scope, element, attr, interpolateValueFn, interpolateTextFn);
28854                 }
28855               };
28856             }
28857           };
28858         }];
28859
28860         var styleDirective = valueFn({
28861           restrict: 'E',
28862           terminal: false
28863         });
28864
28865         var requiredDirective = function() {
28866           return {
28867             restrict: 'A',
28868             require: '?ngModel',
28869             link: function(scope, elm, attr, ctrl) {
28870               if (!ctrl) return;
28871               attr.required = true; // force truthy in case we are on non input element
28872
28873               ctrl.$validators.required = function(modelValue, viewValue) {
28874                 return !attr.required || !ctrl.$isEmpty(viewValue);
28875               };
28876
28877               attr.$observe('required', function() {
28878                 ctrl.$validate();
28879               });
28880             }
28881           };
28882         };
28883
28884
28885         var patternDirective = function() {
28886           return {
28887             restrict: 'A',
28888             require: '?ngModel',
28889             link: function(scope, elm, attr, ctrl) {
28890               if (!ctrl) return;
28891
28892               var regexp, patternExp = attr.ngPattern || attr.pattern;
28893               attr.$observe('pattern', function(regex) {
28894                 if (isString(regex) && regex.length > 0) {
28895                   regex = new RegExp('^' + regex + '$');
28896                 }
28897
28898                 if (regex && !regex.test) {
28899                   throw minErr('ngPattern')('noregexp',
28900                     'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
28901                     regex, startingTag(elm));
28902                 }
28903
28904                 regexp = regex || undefined;
28905                 ctrl.$validate();
28906               });
28907
28908               ctrl.$validators.pattern = function(modelValue, viewValue) {
28909                 // HTML5 pattern constraint validates the input value, so we validate the viewValue
28910                 return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
28911               };
28912             }
28913           };
28914         };
28915
28916
28917         var maxlengthDirective = function() {
28918           return {
28919             restrict: 'A',
28920             require: '?ngModel',
28921             link: function(scope, elm, attr, ctrl) {
28922               if (!ctrl) return;
28923
28924               var maxlength = -1;
28925               attr.$observe('maxlength', function(value) {
28926                 var intVal = toInt(value);
28927                 maxlength = isNaN(intVal) ? -1 : intVal;
28928                 ctrl.$validate();
28929               });
28930               ctrl.$validators.maxlength = function(modelValue, viewValue) {
28931                 return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
28932               };
28933             }
28934           };
28935         };
28936
28937         var minlengthDirective = function() {
28938           return {
28939             restrict: 'A',
28940             require: '?ngModel',
28941             link: function(scope, elm, attr, ctrl) {
28942               if (!ctrl) return;
28943
28944               var minlength = 0;
28945               attr.$observe('minlength', function(value) {
28946                 minlength = toInt(value) || 0;
28947                 ctrl.$validate();
28948               });
28949               ctrl.$validators.minlength = function(modelValue, viewValue) {
28950                 return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
28951               };
28952             }
28953           };
28954         };
28955
28956         if (window.angular.bootstrap) {
28957           //AngularJS is already loaded, so we can return here...
28958           console.log('WARNING: Tried to load angular more than once.');
28959           return;
28960         }
28961
28962         //try to bind to jquery now so that one can write jqLite(document).ready()
28963         //but we will rebind on bootstrap again.
28964         bindJQuery();
28965
28966         publishExternalAPI(angular);
28967
28968         angular.module("ngLocale", [], ["$provide", function($provide) {
28969         var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
28970         function getDecimals(n) {
28971           n = n + '';
28972           var i = n.indexOf('.');
28973           return (i == -1) ? 0 : n.length - i - 1;
28974         }
28975
28976         function getVF(n, opt_precision) {
28977           var v = opt_precision;
28978
28979           if (undefined === v) {
28980             v = Math.min(getDecimals(n), 3);
28981           }
28982
28983           var base = Math.pow(10, v);
28984           var f = ((n * base) | 0) % base;
28985           return {v: v, f: f};
28986         }
28987
28988         $provide.value("$locale", {
28989           "DATETIME_FORMATS": {
28990             "AMPMS": [
28991               "AM",
28992               "PM"
28993             ],
28994             "DAY": [
28995               "Sunday",
28996               "Monday",
28997               "Tuesday",
28998               "Wednesday",
28999               "Thursday",
29000               "Friday",
29001               "Saturday"
29002             ],
29003             "ERANAMES": [
29004               "Before Christ",
29005               "Anno Domini"
29006             ],
29007             "ERAS": [
29008               "BC",
29009               "AD"
29010             ],
29011             "FIRSTDAYOFWEEK": 6,
29012             "MONTH": [
29013               "January",
29014               "February",
29015               "March",
29016               "April",
29017               "May",
29018               "June",
29019               "July",
29020               "August",
29021               "September",
29022               "October",
29023               "November",
29024               "December"
29025             ],
29026             "SHORTDAY": [
29027               "Sun",
29028               "Mon",
29029               "Tue",
29030               "Wed",
29031               "Thu",
29032               "Fri",
29033               "Sat"
29034             ],
29035             "SHORTMONTH": [
29036               "Jan",
29037               "Feb",
29038               "Mar",
29039               "Apr",
29040               "May",
29041               "Jun",
29042               "Jul",
29043               "Aug",
29044               "Sep",
29045               "Oct",
29046               "Nov",
29047               "Dec"
29048             ],
29049             "WEEKENDRANGE": [
29050               5,
29051               6
29052             ],
29053             "fullDate": "EEEE, MMMM d, y",
29054             "longDate": "MMMM d, y",
29055             "medium": "MMM d, y h:mm:ss a",
29056             "mediumDate": "MMM d, y",
29057             "mediumTime": "h:mm:ss a",
29058             "short": "M/d/yy h:mm a",
29059             "shortDate": "M/d/yy",
29060             "shortTime": "h:mm a"
29061           },
29062           "NUMBER_FORMATS": {
29063             "CURRENCY_SYM": "$",
29064             "DECIMAL_SEP": ".",
29065             "GROUP_SEP": ",",
29066             "PATTERNS": [
29067               {
29068                 "gSize": 3,
29069                 "lgSize": 3,
29070                 "maxFrac": 3,
29071                 "minFrac": 0,
29072                 "minInt": 1,
29073                 "negPre": "-",
29074                 "negSuf": "",
29075                 "posPre": "",
29076                 "posSuf": ""
29077               },
29078               {
29079                 "gSize": 3,
29080                 "lgSize": 3,
29081                 "maxFrac": 2,
29082                 "minFrac": 2,
29083                 "minInt": 1,
29084                 "negPre": "-\u00a4",
29085                 "negSuf": "",
29086                 "posPre": "\u00a4",
29087                 "posSuf": ""
29088               }
29089             ]
29090           },
29091           "id": "en-us",
29092           "pluralCat": function(n, opt_precision) {  var i = n | 0;  var vf = getVF(n, opt_precision);  if (i == 1 && vf.v == 0) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;}
29093         });
29094         }]);
29095
29096           jqLite(document).ready(function() {
29097             angularInit(document, bootstrap);
29098           });
29099
29100         })(window, document);
29101
29102         !window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
29103
29104 /***/ },
29105 /* 3 */
29106 /***/ function(module, exports) {
29107
29108         /**
29109          * State-based routing for AngularJS
29110 <<<<<<< HEAD
29111          * @version v0.2.18
29112 =======
29113          * @version v0.2.15
29114 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29115          * @link http://angular-ui.github.com/
29116          * @license MIT License, http://www.opensource.org/licenses/MIT
29117          */
29118
29119         /* commonjs package manager support (eg componentjs) */
29120         if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports){
29121           module.exports = 'ui.router';
29122         }
29123
29124         (function (window, angular, undefined) {
29125         /*jshint globalstrict:true*/
29126         /*global angular:false*/
29127         'use strict';
29128
29129         var isDefined = angular.isDefined,
29130             isFunction = angular.isFunction,
29131             isString = angular.isString,
29132             isObject = angular.isObject,
29133             isArray = angular.isArray,
29134             forEach = angular.forEach,
29135             extend = angular.extend,
29136 <<<<<<< HEAD
29137             copy = angular.copy,
29138             toJson = angular.toJson;
29139 =======
29140             copy = angular.copy;
29141 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29142
29143         function inherit(parent, extra) {
29144           return extend(new (extend(function() {}, { prototype: parent }))(), extra);
29145         }
29146
29147         function merge(dst) {
29148           forEach(arguments, function(obj) {
29149             if (obj !== dst) {
29150               forEach(obj, function(value, key) {
29151                 if (!dst.hasOwnProperty(key)) dst[key] = value;
29152               });
29153             }
29154           });
29155           return dst;
29156         }
29157
29158         /**
29159          * Finds the common ancestor path between two states.
29160          *
29161          * @param {Object} first The first state.
29162          * @param {Object} second The second state.
29163          * @return {Array} Returns an array of state names in descending order, not including the root.
29164          */
29165         function ancestors(first, second) {
29166           var path = [];
29167
29168           for (var n in first.path) {
29169             if (first.path[n] !== second.path[n]) break;
29170             path.push(first.path[n]);
29171           }
29172           return path;
29173         }
29174
29175         /**
29176          * IE8-safe wrapper for `Object.keys()`.
29177          *
29178          * @param {Object} object A JavaScript object.
29179          * @return {Array} Returns the keys of the object as an array.
29180          */
29181         function objectKeys(object) {
29182           if (Object.keys) {
29183             return Object.keys(object);
29184           }
29185           var result = [];
29186
29187           forEach(object, function(val, key) {
29188             result.push(key);
29189           });
29190           return result;
29191         }
29192
29193         /**
29194          * IE8-safe wrapper for `Array.prototype.indexOf()`.
29195          *
29196          * @param {Array} array A JavaScript array.
29197          * @param {*} value A value to search the array for.
29198          * @return {Number} Returns the array index value of `value`, or `-1` if not present.
29199          */
29200         function indexOf(array, value) {
29201           if (Array.prototype.indexOf) {
29202             return array.indexOf(value, Number(arguments[2]) || 0);
29203           }
29204           var len = array.length >>> 0, from = Number(arguments[2]) || 0;
29205           from = (from < 0) ? Math.ceil(from) : Math.floor(from);
29206
29207           if (from < 0) from += len;
29208
29209           for (; from < len; from++) {
29210             if (from in array && array[from] === value) return from;
29211           }
29212           return -1;
29213         }
29214
29215         /**
29216          * Merges a set of parameters with all parameters inherited between the common parents of the
29217          * current state and a given destination state.
29218          *
29219          * @param {Object} currentParams The value of the current state parameters ($stateParams).
29220          * @param {Object} newParams The set of parameters which will be composited with inherited params.
29221          * @param {Object} $current Internal definition of object representing the current state.
29222          * @param {Object} $to Internal definition of object representing state to transition to.
29223          */
29224         function inheritParams(currentParams, newParams, $current, $to) {
29225           var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];
29226
29227           for (var i in parents) {
29228 <<<<<<< HEAD
29229             if (!parents[i] || !parents[i].params) continue;
29230 =======
29231             if (!parents[i].params) continue;
29232 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29233             parentParams = objectKeys(parents[i].params);
29234             if (!parentParams.length) continue;
29235
29236             for (var j in parentParams) {
29237               if (indexOf(inheritList, parentParams[j]) >= 0) continue;
29238               inheritList.push(parentParams[j]);
29239               inherited[parentParams[j]] = currentParams[parentParams[j]];
29240             }
29241           }
29242           return extend({}, inherited, newParams);
29243         }
29244
29245         /**
29246          * Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
29247          *
29248          * @param {Object} a The first object.
29249          * @param {Object} b The second object.
29250          * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
29251          *                     it defaults to the list of keys in `a`.
29252          * @return {Boolean} Returns `true` if the keys match, otherwise `false`.
29253          */
29254         function equalForKeys(a, b, keys) {
29255           if (!keys) {
29256             keys = [];
29257             for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
29258           }
29259
29260           for (var i=0; i<keys.length; i++) {
29261             var k = keys[i];
29262             if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
29263           }
29264           return true;
29265         }
29266
29267         /**
29268          * Returns the subset of an object, based on a list of keys.
29269          *
29270          * @param {Array} keys
29271          * @param {Object} values
29272          * @return {Boolean} Returns a subset of `values`.
29273          */
29274         function filterByKeys(keys, values) {
29275           var filtered = {};
29276
29277           forEach(keys, function (name) {
29278             filtered[name] = values[name];
29279           });
29280           return filtered;
29281         }
29282
29283         // like _.indexBy
29284         // when you know that your index values will be unique, or you want last-one-in to win
29285         function indexBy(array, propName) {
29286           var result = {};
29287           forEach(array, function(item) {
29288             result[item[propName]] = item;
29289           });
29290           return result;
29291         }
29292
29293         // extracted from underscore.js
29294         // Return a copy of the object only containing the whitelisted properties.
29295         function pick(obj) {
29296           var copy = {};
29297           var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
29298           forEach(keys, function(key) {
29299             if (key in obj) copy[key] = obj[key];
29300           });
29301           return copy;
29302         }
29303
29304         // extracted from underscore.js
29305         // Return a copy of the object omitting the blacklisted properties.
29306         function omit(obj) {
29307           var copy = {};
29308           var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
29309           for (var key in obj) {
29310             if (indexOf(keys, key) == -1) copy[key] = obj[key];
29311           }
29312           return copy;
29313         }
29314
29315         function pluck(collection, key) {
29316           var result = isArray(collection) ? [] : {};
29317
29318           forEach(collection, function(val, i) {
29319             result[i] = isFunction(key) ? key(val) : val[key];
29320           });
29321           return result;
29322         }
29323
29324         function filter(collection, callback) {
29325           var array = isArray(collection);
29326           var result = array ? [] : {};
29327           forEach(collection, function(val, i) {
29328             if (callback(val, i)) {
29329               result[array ? result.length : i] = val;
29330             }
29331           });
29332           return result;
29333         }
29334
29335         function map(collection, callback) {
29336           var result = isArray(collection) ? [] : {};
29337
29338           forEach(collection, function(val, i) {
29339             result[i] = callback(val, i);
29340           });
29341           return result;
29342         }
29343
29344         /**
29345          * @ngdoc overview
29346          * @name ui.router.util
29347          *
29348          * @description
29349          * # ui.router.util sub-module
29350          *
29351          * This module is a dependency of other sub-modules. Do not include this module as a dependency
29352          * in your angular app (use {@link ui.router} module instead).
29353          *
29354          */
29355         angular.module('ui.router.util', ['ng']);
29356
29357         /**
29358          * @ngdoc overview
29359          * @name ui.router.router
29360          * 
29361          * @requires ui.router.util
29362          *
29363          * @description
29364          * # ui.router.router sub-module
29365          *
29366          * This module is a dependency of other sub-modules. Do not include this module as a dependency
29367          * in your angular app (use {@link ui.router} module instead).
29368          */
29369         angular.module('ui.router.router', ['ui.router.util']);
29370
29371         /**
29372          * @ngdoc overview
29373          * @name ui.router.state
29374          * 
29375          * @requires ui.router.router
29376          * @requires ui.router.util
29377          *
29378          * @description
29379          * # ui.router.state sub-module
29380          *
29381          * This module is a dependency of the main ui.router module. Do not include this module as a dependency
29382          * in your angular app (use {@link ui.router} module instead).
29383          * 
29384          */
29385         angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
29386
29387         /**
29388          * @ngdoc overview
29389          * @name ui.router
29390          *
29391          * @requires ui.router.state
29392          *
29393          * @description
29394          * # ui.router
29395          * 
29396          * ## The main module for ui.router 
29397          * There are several sub-modules included with the ui.router module, however only this module is needed
29398          * as a dependency within your angular app. The other modules are for organization purposes. 
29399          *
29400          * The modules are:
29401          * * ui.router - the main "umbrella" module
29402          * * ui.router.router - 
29403          * 
29404          * *You'll need to include **only** this module as the dependency within your angular app.*
29405          * 
29406          * <pre>
29407          * <!doctype html>
29408          * <html ng-app="myApp">
29409          * <head>
29410          *   <script src="js/angular.js"></script>
29411          *   <!-- Include the ui-router script -->
29412          *   <script src="js/angular-ui-router.min.js"></script>
29413          *   <script>
29414          *     // ...and add 'ui.router' as a dependency
29415          *     var myApp = angular.module('myApp', ['ui.router']);
29416          *   </script>
29417          * </head>
29418          * <body>
29419          * </body>
29420          * </html>
29421          * </pre>
29422          */
29423         angular.module('ui.router', ['ui.router.state']);
29424
29425         angular.module('ui.router.compat', ['ui.router']);
29426
29427         /**
29428          * @ngdoc object
29429          * @name ui.router.util.$resolve
29430          *
29431          * @requires $q
29432          * @requires $injector
29433          *
29434          * @description
29435          * Manages resolution of (acyclic) graphs of promises.
29436          */
29437         $Resolve.$inject = ['$q', '$injector'];
29438         function $Resolve(  $q,    $injector) {
29439           
29440           var VISIT_IN_PROGRESS = 1,
29441               VISIT_DONE = 2,
29442               NOTHING = {},
29443               NO_DEPENDENCIES = [],
29444               NO_LOCALS = NOTHING,
29445               NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING });
29446           
29447
29448           /**
29449            * @ngdoc function
29450            * @name ui.router.util.$resolve#study
29451            * @methodOf ui.router.util.$resolve
29452            *
29453            * @description
29454            * Studies a set of invocables that are likely to be used multiple times.
29455            * <pre>
29456            * $resolve.study(invocables)(locals, parent, self)
29457            * </pre>
29458            * is equivalent to
29459            * <pre>
29460            * $resolve.resolve(invocables, locals, parent, self)
29461            * </pre>
29462            * but the former is more efficient (in fact `resolve` just calls `study` 
29463            * internally).
29464            *
29465            * @param {object} invocables Invocable objects
29466            * @return {function} a function to pass in locals, parent and self
29467            */
29468           this.study = function (invocables) {
29469             if (!isObject(invocables)) throw new Error("'invocables' must be an object");
29470             var invocableKeys = objectKeys(invocables || {});
29471             
29472             // Perform a topological sort of invocables to build an ordered plan
29473             var plan = [], cycle = [], visited = {};
29474             function visit(value, key) {
29475               if (visited[key] === VISIT_DONE) return;
29476               
29477               cycle.push(key);
29478               if (visited[key] === VISIT_IN_PROGRESS) {
29479                 cycle.splice(0, indexOf(cycle, key));
29480                 throw new Error("Cyclic dependency: " + cycle.join(" -> "));
29481               }
29482               visited[key] = VISIT_IN_PROGRESS;
29483               
29484               if (isString(value)) {
29485                 plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES);
29486               } else {
29487                 var params = $injector.annotate(value);
29488                 forEach(params, function (param) {
29489                   if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param);
29490                 });
29491                 plan.push(key, value, params);
29492               }
29493               
29494               cycle.pop();
29495               visited[key] = VISIT_DONE;
29496             }
29497             forEach(invocables, visit);
29498             invocables = cycle = visited = null; // plan is all that's required
29499             
29500             function isResolve(value) {
29501               return isObject(value) && value.then && value.$$promises;
29502             }
29503             
29504             return function (locals, parent, self) {
29505               if (isResolve(locals) && self === undefined) {
29506                 self = parent; parent = locals; locals = null;
29507               }
29508               if (!locals) locals = NO_LOCALS;
29509               else if (!isObject(locals)) {
29510                 throw new Error("'locals' must be an object");
29511               }       
29512               if (!parent) parent = NO_PARENT;
29513               else if (!isResolve(parent)) {
29514                 throw new Error("'parent' must be a promise returned by $resolve.resolve()");
29515               }
29516               
29517               // To complete the overall resolution, we have to wait for the parent
29518               // promise and for the promise for each invokable in our plan.
29519               var resolution = $q.defer(),
29520                   result = resolution.promise,
29521                   promises = result.$$promises = {},
29522                   values = extend({}, locals),
29523                   wait = 1 + plan.length/3,
29524                   merged = false;
29525                   
29526               function done() {
29527                 // Merge parent values we haven't got yet and publish our own $$values
29528                 if (!--wait) {
29529                   if (!merged) merge(values, parent.$$values); 
29530                   result.$$values = values;
29531                   result.$$promises = result.$$promises || true; // keep for isResolve()
29532                   delete result.$$inheritedValues;
29533                   resolution.resolve(values);
29534                 }
29535               }
29536               
29537               function fail(reason) {
29538                 result.$$failure = reason;
29539                 resolution.reject(reason);
29540               }
29541
29542               // Short-circuit if parent has already failed
29543               if (isDefined(parent.$$failure)) {
29544                 fail(parent.$$failure);
29545                 return result;
29546               }
29547               
29548               if (parent.$$inheritedValues) {
29549                 merge(values, omit(parent.$$inheritedValues, invocableKeys));
29550               }
29551
29552               // Merge parent values if the parent has already resolved, or merge
29553               // parent promises and wait if the parent resolve is still in progress.
29554               extend(promises, parent.$$promises);
29555               if (parent.$$values) {
29556                 merged = merge(values, omit(parent.$$values, invocableKeys));
29557                 result.$$inheritedValues = omit(parent.$$values, invocableKeys);
29558                 done();
29559               } else {
29560                 if (parent.$$inheritedValues) {
29561                   result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys);
29562                 }        
29563                 parent.then(done, fail);
29564               }
29565               
29566               // Process each invocable in the plan, but ignore any where a local of the same name exists.
29567               for (var i=0, ii=plan.length; i<ii; i+=3) {
29568                 if (locals.hasOwnProperty(plan[i])) done();
29569                 else invoke(plan[i], plan[i+1], plan[i+2]);
29570               }
29571               
29572               function invoke(key, invocable, params) {
29573                 // Create a deferred for this invocation. Failures will propagate to the resolution as well.
29574                 var invocation = $q.defer(), waitParams = 0;
29575                 function onfailure(reason) {
29576                   invocation.reject(reason);
29577                   fail(reason);
29578                 }
29579                 // Wait for any parameter that we have a promise for (either from parent or from this
29580                 // resolve; in that case study() will have made sure it's ordered before us in the plan).
29581                 forEach(params, function (dep) {
29582                   if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) {
29583                     waitParams++;
29584                     promises[dep].then(function (result) {
29585                       values[dep] = result;
29586                       if (!(--waitParams)) proceed();
29587                     }, onfailure);
29588                   }
29589                 });
29590                 if (!waitParams) proceed();
29591                 function proceed() {
29592                   if (isDefined(result.$$failure)) return;
29593                   try {
29594                     invocation.resolve($injector.invoke(invocable, self, values));
29595                     invocation.promise.then(function (result) {
29596                       values[key] = result;
29597                       done();
29598                     }, onfailure);
29599                   } catch (e) {
29600                     onfailure(e);
29601                   }
29602                 }
29603                 // Publish promise synchronously; invocations further down in the plan may depend on it.
29604                 promises[key] = invocation.promise;
29605               }
29606               
29607               return result;
29608             };
29609           };
29610           
29611           /**
29612            * @ngdoc function
29613            * @name ui.router.util.$resolve#resolve
29614            * @methodOf ui.router.util.$resolve
29615            *
29616            * @description
29617            * Resolves a set of invocables. An invocable is a function to be invoked via 
29618            * `$injector.invoke()`, and can have an arbitrary number of dependencies. 
29619            * An invocable can either return a value directly,
29620            * or a `$q` promise. If a promise is returned it will be resolved and the 
29621            * resulting value will be used instead. Dependencies of invocables are resolved 
29622            * (in this order of precedence)
29623            *
29624            * - from the specified `locals`
29625            * - from another invocable that is part of this `$resolve` call
29626            * - from an invocable that is inherited from a `parent` call to `$resolve` 
29627            *   (or recursively
29628            * - from any ancestor `$resolve` of that parent).
29629            *
29630            * The return value of `$resolve` is a promise for an object that contains 
29631            * (in this order of precedence)
29632            *
29633            * - any `locals` (if specified)
29634            * - the resolved return values of all injectables
29635            * - any values inherited from a `parent` call to `$resolve` (if specified)
29636            *
29637            * The promise will resolve after the `parent` promise (if any) and all promises 
29638            * returned by injectables have been resolved. If any invocable 
29639            * (or `$injector.invoke`) throws an exception, or if a promise returned by an 
29640            * invocable is rejected, the `$resolve` promise is immediately rejected with the 
29641            * same error. A rejection of a `parent` promise (if specified) will likewise be 
29642            * propagated immediately. Once the `$resolve` promise has been rejected, no 
29643            * further invocables will be called.
29644            * 
29645 <<<<<<< HEAD
29646            * Cyclic dependencies between invocables are not permitted and will cause `$resolve`
29647 =======
29648            * Cyclic dependencies between invocables are not permitted and will caues `$resolve`
29649 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29650            * to throw an error. As a special case, an injectable can depend on a parameter 
29651            * with the same name as the injectable, which will be fulfilled from the `parent` 
29652            * injectable of the same name. This allows inherited values to be decorated. 
29653            * Note that in this case any other injectable in the same `$resolve` with the same
29654            * dependency would see the decorated value, not the inherited value.
29655            *
29656            * Note that missing dependencies -- unlike cyclic dependencies -- will cause an 
29657            * (asynchronous) rejection of the `$resolve` promise rather than a (synchronous) 
29658            * exception.
29659            *
29660            * Invocables are invoked eagerly as soon as all dependencies are available. 
29661            * This is true even for dependencies inherited from a `parent` call to `$resolve`.
29662            *
29663            * As a special case, an invocable can be a string, in which case it is taken to 
29664            * be a service name to be passed to `$injector.get()`. This is supported primarily 
29665            * for backwards-compatibility with the `resolve` property of `$routeProvider` 
29666            * routes.
29667            *
29668            * @param {object} invocables functions to invoke or 
29669            * `$injector` services to fetch.
29670            * @param {object} locals  values to make available to the injectables
29671            * @param {object} parent  a promise returned by another call to `$resolve`.
29672            * @param {object} self  the `this` for the invoked methods
29673            * @return {object} Promise for an object that contains the resolved return value
29674            * of all invocables, as well as any inherited and local values.
29675            */
29676           this.resolve = function (invocables, locals, parent, self) {
29677             return this.study(invocables)(locals, parent, self);
29678           };
29679         }
29680
29681         angular.module('ui.router.util').service('$resolve', $Resolve);
29682
29683
29684         /**
29685          * @ngdoc object
29686          * @name ui.router.util.$templateFactory
29687          *
29688          * @requires $http
29689          * @requires $templateCache
29690          * @requires $injector
29691          *
29692          * @description
29693          * Service. Manages loading of templates.
29694          */
29695         $TemplateFactory.$inject = ['$http', '$templateCache', '$injector'];
29696         function $TemplateFactory(  $http,   $templateCache,   $injector) {
29697
29698           /**
29699            * @ngdoc function
29700            * @name ui.router.util.$templateFactory#fromConfig
29701            * @methodOf ui.router.util.$templateFactory
29702            *
29703            * @description
29704            * Creates a template from a configuration object. 
29705            *
29706            * @param {object} config Configuration object for which to load a template. 
29707            * The following properties are search in the specified order, and the first one 
29708            * that is defined is used to create the template:
29709            *
29710            * @param {string|object} config.template html string template or function to 
29711            * load via {@link ui.router.util.$templateFactory#fromString fromString}.
29712            * @param {string|object} config.templateUrl url to load or a function returning 
29713            * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
29714            * @param {Function} config.templateProvider function to invoke via 
29715            * {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
29716            * @param {object} params  Parameters to pass to the template function.
29717            * @param {object} locals Locals to pass to `invoke` if the template is loaded 
29718            * via a `templateProvider`. Defaults to `{ params: params }`.
29719            *
29720            * @return {string|object}  The template html as a string, or a promise for 
29721            * that string,or `null` if no template is configured.
29722            */
29723           this.fromConfig = function (config, params, locals) {
29724             return (
29725               isDefined(config.template) ? this.fromString(config.template, params) :
29726               isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
29727               isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
29728               null
29729             );
29730           };
29731
29732           /**
29733            * @ngdoc function
29734            * @name ui.router.util.$templateFactory#fromString
29735            * @methodOf ui.router.util.$templateFactory
29736            *
29737            * @description
29738            * Creates a template from a string or a function returning a string.
29739            *
29740            * @param {string|object} template html template as a string or function that 
29741            * returns an html template as a string.
29742            * @param {object} params Parameters to pass to the template function.
29743            *
29744            * @return {string|object} The template html as a string, or a promise for that 
29745            * string.
29746            */
29747           this.fromString = function (template, params) {
29748             return isFunction(template) ? template(params) : template;
29749           };
29750
29751           /**
29752            * @ngdoc function
29753            * @name ui.router.util.$templateFactory#fromUrl
29754            * @methodOf ui.router.util.$templateFactory
29755            * 
29756            * @description
29757            * Loads a template from the a URL via `$http` and `$templateCache`.
29758            *
29759            * @param {string|Function} url url of the template to load, or a function 
29760            * that returns a url.
29761            * @param {Object} params Parameters to pass to the url function.
29762            * @return {string|Promise.<string>} The template html as a string, or a promise 
29763            * for that string.
29764            */
29765           this.fromUrl = function (url, params) {
29766             if (isFunction(url)) url = url(params);
29767             if (url == null) return null;
29768             else return $http
29769                 .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }})
29770                 .then(function(response) { return response.data; });
29771           };
29772
29773           /**
29774            * @ngdoc function
29775            * @name ui.router.util.$templateFactory#fromProvider
29776            * @methodOf ui.router.util.$templateFactory
29777            *
29778            * @description
29779            * Creates a template by invoking an injectable provider function.
29780            *
29781            * @param {Function} provider Function to invoke via `$injector.invoke`
29782            * @param {Object} params Parameters for the template.
29783            * @param {Object} locals Locals to pass to `invoke`. Defaults to 
29784            * `{ params: params }`.
29785            * @return {string|Promise.<string>} The template html as a string, or a promise 
29786            * for that string.
29787            */
29788           this.fromProvider = function (provider, params, locals) {
29789             return $injector.invoke(provider, null, locals || { params: params });
29790           };
29791         }
29792
29793         angular.module('ui.router.util').service('$templateFactory', $TemplateFactory);
29794
29795         var $$UMFP; // reference to $UrlMatcherFactoryProvider
29796
29797         /**
29798          * @ngdoc object
29799          * @name ui.router.util.type:UrlMatcher
29800          *
29801          * @description
29802          * Matches URLs against patterns and extracts named parameters from the path or the search
29803          * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list
29804          * of search parameters. Multiple search parameter names are separated by '&'. Search parameters
29805          * do not influence whether or not a URL is matched, but their values are passed through into
29806          * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}.
29807          *
29808          * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace
29809          * syntax, which optionally allows a regular expression for the parameter to be specified:
29810          *
29811          * * `':'` name - colon placeholder
29812          * * `'*'` name - catch-all placeholder
29813          * * `'{' name '}'` - curly placeholder
29814          * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the
29815          *   regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.
29816          *
29817          * Parameter names may contain only word characters (latin letters, digits, and underscore) and
29818          * must be unique within the pattern (across both path and search parameters). For colon
29819          * placeholders or curly placeholders without an explicit regexp, a path parameter matches any
29820          * number of characters other than '/'. For catch-all placeholders the path parameter matches
29821          * any number of characters.
29822          *
29823          * Examples:
29824          *
29825          * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for
29826          *   trailing slashes, and patterns have to match the entire path, not just a prefix.
29827          * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
29828          *   '/user/bob/details'. The second path segment will be captured as the parameter 'id'.
29829          * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax.
29830          * * `'/user/{id:[^/]*}'` - Same as the previous example.
29831          * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id
29832          *   parameter consists of 1 to 8 hex digits.
29833          * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the
29834          *   path into the parameter 'path'.
29835          * * `'/files/*path'` - ditto.
29836          * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined
29837          *   in the built-in  `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start
29838          *
29839          * @param {string} pattern  The pattern to compile into a matcher.
29840          * @param {Object} config  A configuration object hash:
29841          * @param {Object=} parentMatcher Used to concatenate the pattern/config onto
29842          *   an existing UrlMatcher
29843          *
29844          * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.
29845          * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.
29846          *
29847          * @property {string} prefix  A static prefix of this pattern. The matcher guarantees that any
29848          *   URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns
29849          *   non-null) will start with this prefix.
29850          *
29851          * @property {string} source  The pattern that was passed into the constructor
29852          *
29853          * @property {string} sourcePath  The path portion of the source property
29854          *
29855          * @property {string} sourceSearch  The search portion of the source property
29856          *
29857          * @property {string} regex  The constructed regex that will be used to match against the url when
29858          *   it is time to determine which url will match.
29859          *
29860          * @returns {Object}  New `UrlMatcher` object
29861          */
29862         function UrlMatcher(pattern, config, parentMatcher) {
29863           config = extend({ params: {} }, isObject(config) ? config : {});
29864
29865           // Find all placeholders and create a compiled pattern, using either classic or curly syntax:
29866           //   '*' name
29867           //   ':' name
29868           //   '{' name '}'
29869           //   '{' name ':' regexp '}'
29870           // The regular expression is somewhat complicated due to the need to allow curly braces
29871           // inside the regular expression. The placeholder regexp breaks down as follows:
29872           //    ([:*])([\w\[\]]+)              - classic placeholder ($1 / $2) (search version has - for snake-case)
29873 <<<<<<< HEAD
29874           //    \{([\w\[\]]+)(?:\:\s*( ... ))?\}  - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case
29875 =======
29876           //    \{([\w\[\]]+)(?:\:( ... ))?\}  - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case
29877 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29878           //    (?: ... | ... | ... )+         - the regexp consists of any number of atoms, an atom being either
29879           //    [^{}\\]+                       - anything other than curly braces or backslash
29880           //    \\.                            - a backslash escape
29881           //    \{(?:[^{}\\]+|\\.)*\}          - a matched set of curly braces containing other atoms
29882 <<<<<<< HEAD
29883           var placeholder       = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
29884               searchPlaceholder = /([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
29885 =======
29886           var placeholder       = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
29887               searchPlaceholder = /([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
29888 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29889               compiled = '^', last = 0, m,
29890               segments = this.segments = [],
29891               parentParams = parentMatcher ? parentMatcher.params : {},
29892               params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(),
29893               paramNames = [];
29894
29895           function addParameter(id, type, config, location) {
29896             paramNames.push(id);
29897             if (parentParams[id]) return parentParams[id];
29898 <<<<<<< HEAD
29899             if (!/^\w+([-.]+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
29900 =======
29901             if (!/^\w+(-+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
29902 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29903             if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
29904             params[id] = new $$UMFP.Param(id, type, config, location);
29905             return params[id];
29906           }
29907
29908           function quoteRegExp(string, pattern, squash, optional) {
29909             var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&");
29910             if (!pattern) return result;
29911             switch(squash) {
29912               case false: surroundPattern = ['(', ')' + (optional ? "?" : "")]; break;
29913 <<<<<<< HEAD
29914               case true:
29915                 result = result.replace(/\/$/, '');
29916                 surroundPattern = ['(?:\/(', ')|\/)?'];
29917               break;
29918 =======
29919               case true:  surroundPattern = ['?(', ')?']; break;
29920 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29921               default:    surroundPattern = ['(' + squash + "|", ')?']; break;
29922             }
29923             return result + surroundPattern[0] + pattern + surroundPattern[1];
29924           }
29925
29926           this.source = pattern;
29927
29928           // Split into static segments separated by path parameter placeholders.
29929           // The number of segments is always 1 more than the number of parameters.
29930           function matchDetails(m, isSearch) {
29931             var id, regexp, segment, type, cfg, arrayMode;
29932             id          = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null
29933             cfg         = config.params[id];
29934             segment     = pattern.substring(last, m.index);
29935             regexp      = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null);
29936 <<<<<<< HEAD
29937
29938             if (regexp) {
29939               type      = $$UMFP.type(regexp) || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp, config.caseInsensitive ? 'i' : undefined) });
29940             }
29941
29942 =======
29943             type        = $$UMFP.type(regexp || "string") || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp, config.caseInsensitive ? 'i' : undefined) });
29944 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
29945             return {
29946               id: id, regexp: regexp, segment: segment, type: type, cfg: cfg
29947             };
29948           }
29949
29950           var p, param, segment;
29951           while ((m = placeholder.exec(pattern))) {
29952             p = matchDetails(m, false);
29953             if (p.segment.indexOf('?') >= 0) break; // we're into the search part
29954
29955             param = addParameter(p.id, p.type, p.cfg, "path");
29956             compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash, param.isOptional);
29957             segments.push(p.segment);
29958             last = placeholder.lastIndex;
29959           }
29960           segment = pattern.substring(last);
29961
29962           // Find any search parameter names and remove them from the last segment
29963           var i = segment.indexOf('?');
29964
29965           if (i >= 0) {
29966             var search = this.sourceSearch = segment.substring(i);
29967             segment = segment.substring(0, i);
29968             this.sourcePath = pattern.substring(0, last + i);
29969
29970             if (search.length > 0) {
29971               last = 0;
29972               while ((m = searchPlaceholder.exec(search))) {
29973                 p = matchDetails(m, true);
29974                 param = addParameter(p.id, p.type, p.cfg, "search");
29975                 last = placeholder.lastIndex;
29976                 // check if ?&
29977               }
29978             }
29979           } else {
29980             this.sourcePath = pattern;
29981             this.sourceSearch = '';
29982           }
29983
29984           compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$';
29985           segments.push(segment);
29986
29987           this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined);
29988           this.prefix = segments[0];
29989           this.$$paramNames = paramNames;
29990         }
29991
29992         /**
29993          * @ngdoc function
29994          * @name ui.router.util.type:UrlMatcher#concat
29995          * @methodOf ui.router.util.type:UrlMatcher
29996          *
29997          * @description
29998          * Returns a new matcher for a pattern constructed by appending the path part and adding the
29999          * search parameters of the specified pattern to this pattern. The current pattern is not
30000          * modified. This can be understood as creating a pattern for URLs that are relative to (or
30001          * suffixes of) the current pattern.
30002          *
30003          * @example
30004          * The following two matchers are equivalent:
30005          * <pre>
30006          * new UrlMatcher('/user/{id}?q').concat('/details?date');
30007          * new UrlMatcher('/user/{id}/details?q&date');
30008          * </pre>
30009          *
30010          * @param {string} pattern  The pattern to append.
30011          * @param {Object} config  An object hash of the configuration for the matcher.
30012          * @returns {UrlMatcher}  A matcher for the concatenated pattern.
30013          */
30014         UrlMatcher.prototype.concat = function (pattern, config) {
30015           // Because order of search parameters is irrelevant, we can add our own search
30016           // parameters to the end of the new pattern. Parse the new pattern by itself
30017           // and then join the bits together, but it's much easier to do this on a string level.
30018           var defaultConfig = {
30019             caseInsensitive: $$UMFP.caseInsensitive(),
30020             strict: $$UMFP.strictMode(),
30021             squash: $$UMFP.defaultSquashPolicy()
30022           };
30023           return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this);
30024         };
30025
30026         UrlMatcher.prototype.toString = function () {
30027           return this.source;
30028         };
30029
30030         /**
30031          * @ngdoc function
30032          * @name ui.router.util.type:UrlMatcher#exec
30033          * @methodOf ui.router.util.type:UrlMatcher
30034          *
30035          * @description
30036          * Tests the specified path against this matcher, and returns an object containing the captured
30037          * parameter values, or null if the path does not match. The returned object contains the values
30038          * of any search parameters that are mentioned in the pattern, but their value may be null if
30039          * they are not present in `searchParams`. This means that search parameters are always treated
30040          * as optional.
30041          *
30042          * @example
30043          * <pre>
30044          * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
30045          *   x: '1', q: 'hello'
30046          * });
30047          * // returns { id: 'bob', q: 'hello', r: null }
30048          * </pre>
30049          *
30050          * @param {string} path  The URL path to match, e.g. `$location.path()`.
30051          * @param {Object} searchParams  URL search parameters, e.g. `$location.search()`.
30052          * @returns {Object}  The captured parameter values.
30053          */
30054         UrlMatcher.prototype.exec = function (path, searchParams) {
30055           var m = this.regexp.exec(path);
30056           if (!m) return null;
30057           searchParams = searchParams || {};
30058
30059           var paramNames = this.parameters(), nTotal = paramNames.length,
30060             nPath = this.segments.length - 1,
30061             values = {}, i, j, cfg, paramName;
30062
30063           if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'");
30064
30065           function decodePathArray(string) {
30066             function reverseString(str) { return str.split("").reverse().join(""); }
30067             function unquoteDashes(str) { return str.replace(/\\-/g, "-"); }
30068
30069             var split = reverseString(string).split(/-(?!\\)/);
30070             var allReversed = map(split, reverseString);
30071             return map(allReversed, unquoteDashes).reverse();
30072           }
30073
30074 <<<<<<< HEAD
30075           var param, paramVal;
30076           for (i = 0; i < nPath; i++) {
30077             paramName = paramNames[i];
30078             param = this.params[paramName];
30079             paramVal = m[i+1];
30080             // if the param value matches a pre-replace pair, replace the value before decoding.
30081             for (j = 0; j < param.replace.length; j++) {
30082               if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
30083             }
30084             if (paramVal && param.array === true) paramVal = decodePathArray(paramVal);
30085             if (isDefined(paramVal)) paramVal = param.type.decode(paramVal);
30086 =======
30087           for (i = 0; i < nPath; i++) {
30088             paramName = paramNames[i];
30089             var param = this.params[paramName];
30090             var paramVal = m[i+1];
30091             // if the param value matches a pre-replace pair, replace the value before decoding.
30092             for (j = 0; j < param.replace; j++) {
30093               if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
30094             }
30095             if (paramVal && param.array === true) paramVal = decodePathArray(paramVal);
30096 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30097             values[paramName] = param.value(paramVal);
30098           }
30099           for (/**/; i < nTotal; i++) {
30100             paramName = paramNames[i];
30101             values[paramName] = this.params[paramName].value(searchParams[paramName]);
30102 <<<<<<< HEAD
30103             param = this.params[paramName];
30104             paramVal = searchParams[paramName];
30105             for (j = 0; j < param.replace.length; j++) {
30106               if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
30107             }
30108             if (isDefined(paramVal)) paramVal = param.type.decode(paramVal);
30109             values[paramName] = param.value(paramVal);
30110 =======
30111 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30112           }
30113
30114           return values;
30115         };
30116
30117         /**
30118          * @ngdoc function
30119          * @name ui.router.util.type:UrlMatcher#parameters
30120          * @methodOf ui.router.util.type:UrlMatcher
30121          *
30122          * @description
30123          * Returns the names of all path and search parameters of this pattern in an unspecified order.
30124          *
30125          * @returns {Array.<string>}  An array of parameter names. Must be treated as read-only. If the
30126          *    pattern has no parameters, an empty array is returned.
30127          */
30128         UrlMatcher.prototype.parameters = function (param) {
30129           if (!isDefined(param)) return this.$$paramNames;
30130           return this.params[param] || null;
30131         };
30132
30133         /**
30134          * @ngdoc function
30135 <<<<<<< HEAD
30136          * @name ui.router.util.type:UrlMatcher#validates
30137 =======
30138          * @name ui.router.util.type:UrlMatcher#validate
30139 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30140          * @methodOf ui.router.util.type:UrlMatcher
30141          *
30142          * @description
30143          * Checks an object hash of parameters to validate their correctness according to the parameter
30144          * types of this `UrlMatcher`.
30145          *
30146          * @param {Object} params The object hash of parameters to validate.
30147          * @returns {boolean} Returns `true` if `params` validates, otherwise `false`.
30148          */
30149         UrlMatcher.prototype.validates = function (params) {
30150           return this.params.$$validates(params);
30151         };
30152
30153         /**
30154          * @ngdoc function
30155          * @name ui.router.util.type:UrlMatcher#format
30156          * @methodOf ui.router.util.type:UrlMatcher
30157          *
30158          * @description
30159          * Creates a URL that matches this pattern by substituting the specified values
30160          * for the path and search parameters. Null values for path parameters are
30161          * treated as empty strings.
30162          *
30163          * @example
30164          * <pre>
30165          * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
30166          * // returns '/user/bob?q=yes'
30167          * </pre>
30168          *
30169          * @param {Object} values  the values to substitute for the parameters in this pattern.
30170          * @returns {string}  the formatted URL (path and optionally search part).
30171          */
30172         UrlMatcher.prototype.format = function (values) {
30173           values = values || {};
30174           var segments = this.segments, params = this.parameters(), paramset = this.params;
30175           if (!this.validates(values)) return null;
30176
30177           var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0];
30178
30179           function encodeDashes(str) { // Replace dashes with encoded "\-"
30180             return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); });
30181           }
30182
30183           for (i = 0; i < nTotal; i++) {
30184             var isPathParam = i < nPath;
30185             var name = params[i], param = paramset[name], value = param.value(values[name]);
30186             var isDefaultValue = param.isOptional && param.type.equals(param.value(), value);
30187             var squash = isDefaultValue ? param.squash : false;
30188             var encoded = param.type.encode(value);
30189
30190             if (isPathParam) {
30191               var nextSegment = segments[i + 1];
30192 <<<<<<< HEAD
30193               var isFinalPathParam = i + 1 === nPath;
30194
30195 =======
30196 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30197               if (squash === false) {
30198                 if (encoded != null) {
30199                   if (isArray(encoded)) {
30200                     result += map(encoded, encodeDashes).join("-");
30201                   } else {
30202                     result += encodeURIComponent(encoded);
30203                   }
30204                 }
30205                 result += nextSegment;
30206               } else if (squash === true) {
30207                 var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/;
30208                 result += nextSegment.match(capture)[1];
30209               } else if (isString(squash)) {
30210                 result += squash + nextSegment;
30211               }
30212 <<<<<<< HEAD
30213
30214               if (isFinalPathParam && param.squash === true && result.slice(-1) === '/') result = result.slice(0, -1);
30215             } else {
30216               if (encoded == null || (isDefaultValue && squash !== false)) continue;
30217               if (!isArray(encoded)) encoded = [ encoded ];
30218               if (encoded.length === 0) continue;
30219 =======
30220             } else {
30221               if (encoded == null || (isDefaultValue && squash !== false)) continue;
30222               if (!isArray(encoded)) encoded = [ encoded ];
30223 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30224               encoded = map(encoded, encodeURIComponent).join('&' + name + '=');
30225               result += (search ? '&' : '?') + (name + '=' + encoded);
30226               search = true;
30227             }
30228           }
30229
30230           return result;
30231         };
30232
30233         /**
30234          * @ngdoc object
30235          * @name ui.router.util.type:Type
30236          *
30237          * @description
30238          * Implements an interface to define custom parameter types that can be decoded from and encoded to
30239          * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`}
30240          * objects when matching or formatting URLs, or comparing or validating parameter values.
30241          *
30242          * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more
30243          * information on registering custom types.
30244          *
30245          * @param {Object} config  A configuration object which contains the custom type definition.  The object's
30246          *        properties will override the default methods and/or pattern in `Type`'s public interface.
30247          * @example
30248          * <pre>
30249          * {
30250          *   decode: function(val) { return parseInt(val, 10); },
30251          *   encode: function(val) { return val && val.toString(); },
30252          *   equals: function(a, b) { return this.is(a) && a === b; },
30253          *   is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
30254          *   pattern: /\d+/
30255          * }
30256          * </pre>
30257          *
30258          * @property {RegExp} pattern The regular expression pattern used to match values of this type when
30259          *           coming from a substring of a URL.
30260          *
30261          * @returns {Object}  Returns a new `Type` object.
30262          */
30263         function Type(config) {
30264           extend(this, config);
30265         }
30266
30267         /**
30268          * @ngdoc function
30269          * @name ui.router.util.type:Type#is
30270          * @methodOf ui.router.util.type:Type
30271          *
30272          * @description
30273          * Detects whether a value is of a particular type. Accepts a native (decoded) value
30274          * and determines whether it matches the current `Type` object.
30275          *
30276          * @param {*} val  The value to check.
30277          * @param {string} key  Optional. If the type check is happening in the context of a specific
30278          *        {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the
30279          *        parameter in which `val` is stored. Can be used for meta-programming of `Type` objects.
30280          * @returns {Boolean}  Returns `true` if the value matches the type, otherwise `false`.
30281          */
30282         Type.prototype.is = function(val, key) {
30283           return true;
30284         };
30285
30286         /**
30287          * @ngdoc function
30288          * @name ui.router.util.type:Type#encode
30289          * @methodOf ui.router.util.type:Type
30290          *
30291          * @description
30292          * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the
30293          * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it
30294          * only needs to be a representation of `val` that has been coerced to a string.
30295          *
30296          * @param {*} val  The value to encode.
30297          * @param {string} key  The name of the parameter in which `val` is stored. Can be used for
30298          *        meta-programming of `Type` objects.
30299          * @returns {string}  Returns a string representation of `val` that can be encoded in a URL.
30300          */
30301         Type.prototype.encode = function(val, key) {
30302           return val;
30303         };
30304
30305         /**
30306          * @ngdoc function
30307          * @name ui.router.util.type:Type#decode
30308          * @methodOf ui.router.util.type:Type
30309          *
30310          * @description
30311          * Converts a parameter value (from URL string or transition param) to a custom/native value.
30312          *
30313          * @param {string} val  The URL parameter value to decode.
30314          * @param {string} key  The name of the parameter in which `val` is stored. Can be used for
30315          *        meta-programming of `Type` objects.
30316          * @returns {*}  Returns a custom representation of the URL parameter value.
30317          */
30318         Type.prototype.decode = function(val, key) {
30319           return val;
30320         };
30321
30322         /**
30323          * @ngdoc function
30324          * @name ui.router.util.type:Type#equals
30325          * @methodOf ui.router.util.type:Type
30326          *
30327          * @description
30328          * Determines whether two decoded values are equivalent.
30329          *
30330          * @param {*} a  A value to compare against.
30331          * @param {*} b  A value to compare against.
30332          * @returns {Boolean}  Returns `true` if the values are equivalent/equal, otherwise `false`.
30333          */
30334         Type.prototype.equals = function(a, b) {
30335           return a == b;
30336         };
30337
30338         Type.prototype.$subPattern = function() {
30339           var sub = this.pattern.toString();
30340           return sub.substr(1, sub.length - 2);
30341         };
30342
30343         Type.prototype.pattern = /.*/;
30344
30345         Type.prototype.toString = function() { return "{Type:" + this.name + "}"; };
30346
30347         /** Given an encoded string, or a decoded object, returns a decoded object */
30348         Type.prototype.$normalize = function(val) {
30349           return this.is(val) ? val : this.decode(val);
30350         };
30351
30352         /*
30353          * Wraps an existing custom Type as an array of Type, depending on 'mode'.
30354          * e.g.:
30355          * - urlmatcher pattern "/path?{queryParam[]:int}"
30356          * - url: "/path?queryParam=1&queryParam=2
30357          * - $stateParams.queryParam will be [1, 2]
30358          * if `mode` is "auto", then
30359          * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1
30360          * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2]
30361          */
30362         Type.prototype.$asArray = function(mode, isSearch) {
30363           if (!mode) return this;
30364           if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only");
30365
30366           function ArrayType(type, mode) {
30367             function bindTo(type, callbackName) {
30368               return function() {
30369                 return type[callbackName].apply(type, arguments);
30370               };
30371             }
30372
30373             // Wrap non-array value as array
30374             function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); }
30375             // Unwrap array value for "auto" mode. Return undefined for empty array.
30376             function arrayUnwrap(val) {
30377               switch(val.length) {
30378                 case 0: return undefined;
30379                 case 1: return mode === "auto" ? val[0] : val;
30380                 default: return val;
30381               }
30382             }
30383             function falsey(val) { return !val; }
30384
30385             // Wraps type (.is/.encode/.decode) functions to operate on each value of an array
30386             function arrayHandler(callback, allTruthyMode) {
30387               return function handleArray(val) {
30388 <<<<<<< HEAD
30389                 if (isArray(val) && val.length === 0) return val;
30390 =======
30391 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30392                 val = arrayWrap(val);
30393                 var result = map(val, callback);
30394                 if (allTruthyMode === true)
30395                   return filter(result, falsey).length === 0;
30396                 return arrayUnwrap(result);
30397               };
30398             }
30399
30400             // Wraps type (.equals) functions to operate on each value of an array
30401             function arrayEqualsHandler(callback) {
30402               return function handleArray(val1, val2) {
30403                 var left = arrayWrap(val1), right = arrayWrap(val2);
30404                 if (left.length !== right.length) return false;
30405                 for (var i = 0; i < left.length; i++) {
30406                   if (!callback(left[i], right[i])) return false;
30407                 }
30408                 return true;
30409               };
30410             }
30411
30412             this.encode = arrayHandler(bindTo(type, 'encode'));
30413             this.decode = arrayHandler(bindTo(type, 'decode'));
30414             this.is     = arrayHandler(bindTo(type, 'is'), true);
30415             this.equals = arrayEqualsHandler(bindTo(type, 'equals'));
30416             this.pattern = type.pattern;
30417             this.$normalize = arrayHandler(bindTo(type, '$normalize'));
30418             this.name = type.name;
30419             this.$arrayMode = mode;
30420           }
30421
30422           return new ArrayType(this, mode);
30423         };
30424
30425
30426
30427         /**
30428          * @ngdoc object
30429          * @name ui.router.util.$urlMatcherFactory
30430          *
30431          * @description
30432          * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory
30433          * is also available to providers under the name `$urlMatcherFactoryProvider`.
30434          */
30435         function $UrlMatcherFactory() {
30436           $$UMFP = this;
30437
30438           var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false;
30439
30440 <<<<<<< HEAD
30441           // Use tildes to pre-encode slashes.
30442           // If the slashes are simply URLEncoded, the browser can choose to pre-decode them,
30443           // and bidirectional encoding/decoding fails.
30444           // Tilde was chosen because it's not a RFC 3986 section 2.2 Reserved Character
30445           function valToString(val) { return val != null ? val.toString().replace(/~/g, "~~").replace(/\//g, "~2F") : val; }
30446           function valFromString(val) { return val != null ? val.toString().replace(/~2F/g, "/").replace(/~~/g, "~") : val; }
30447
30448           var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {
30449             "string": {
30450 =======
30451           function valToString(val) { return val != null ? val.toString().replace(/\//g, "%2F") : val; }
30452           function valFromString(val) { return val != null ? val.toString().replace(/%2F/g, "/") : val; }
30453
30454           var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {
30455             string: {
30456 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30457               encode: valToString,
30458               decode: valFromString,
30459               // TODO: in 1.0, make string .is() return false if value is undefined/null by default.
30460               // In 0.2.x, string params are optional by default for backwards compat
30461               is: function(val) { return val == null || !isDefined(val) || typeof val === "string"; },
30462               pattern: /[^/]*/
30463             },
30464 <<<<<<< HEAD
30465             "int": {
30466 =======
30467             int: {
30468 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30469               encode: valToString,
30470               decode: function(val) { return parseInt(val, 10); },
30471               is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; },
30472               pattern: /\d+/
30473             },
30474 <<<<<<< HEAD
30475             "bool": {
30476 =======
30477             bool: {
30478 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30479               encode: function(val) { return val ? 1 : 0; },
30480               decode: function(val) { return parseInt(val, 10) !== 0; },
30481               is: function(val) { return val === true || val === false; },
30482               pattern: /0|1/
30483             },
30484 <<<<<<< HEAD
30485             "date": {
30486 =======
30487             date: {
30488 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30489               encode: function (val) {
30490                 if (!this.is(val))
30491                   return undefined;
30492                 return [ val.getFullYear(),
30493                   ('0' + (val.getMonth() + 1)).slice(-2),
30494                   ('0' + val.getDate()).slice(-2)
30495                 ].join("-");
30496               },
30497               decode: function (val) {
30498                 if (this.is(val)) return val;
30499                 var match = this.capture.exec(val);
30500                 return match ? new Date(match[1], match[2] - 1, match[3]) : undefined;
30501               },
30502               is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); },
30503               equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); },
30504               pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,
30505               capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/
30506             },
30507 <<<<<<< HEAD
30508             "json": {
30509 =======
30510             json: {
30511 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30512               encode: angular.toJson,
30513               decode: angular.fromJson,
30514               is: angular.isObject,
30515               equals: angular.equals,
30516               pattern: /[^/]*/
30517             },
30518 <<<<<<< HEAD
30519             "any": { // does not encode/decode
30520 =======
30521             any: { // does not encode/decode
30522 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30523               encode: angular.identity,
30524               decode: angular.identity,
30525               equals: angular.equals,
30526               pattern: /.*/
30527             }
30528           };
30529
30530           function getDefaultConfig() {
30531             return {
30532               strict: isStrictMode,
30533               caseInsensitive: isCaseInsensitive
30534             };
30535           }
30536
30537           function isInjectable(value) {
30538             return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1])));
30539           }
30540
30541           /**
30542            * [Internal] Get the default value of a parameter, which may be an injectable function.
30543            */
30544           $UrlMatcherFactory.$$getDefaultValue = function(config) {
30545             if (!isInjectable(config.value)) return config.value;
30546             if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
30547             return injector.invoke(config.value);
30548           };
30549
30550           /**
30551            * @ngdoc function
30552            * @name ui.router.util.$urlMatcherFactory#caseInsensitive
30553            * @methodOf ui.router.util.$urlMatcherFactory
30554            *
30555            * @description
30556            * Defines whether URL matching should be case sensitive (the default behavior), or not.
30557            *
30558            * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`;
30559            * @returns {boolean} the current value of caseInsensitive
30560            */
30561           this.caseInsensitive = function(value) {
30562             if (isDefined(value))
30563               isCaseInsensitive = value;
30564             return isCaseInsensitive;
30565           };
30566
30567           /**
30568            * @ngdoc function
30569            * @name ui.router.util.$urlMatcherFactory#strictMode
30570            * @methodOf ui.router.util.$urlMatcherFactory
30571            *
30572            * @description
30573            * Defines whether URLs should match trailing slashes, or not (the default behavior).
30574            *
30575            * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`.
30576            * @returns {boolean} the current value of strictMode
30577            */
30578           this.strictMode = function(value) {
30579             if (isDefined(value))
30580               isStrictMode = value;
30581             return isStrictMode;
30582           };
30583
30584           /**
30585            * @ngdoc function
30586            * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy
30587            * @methodOf ui.router.util.$urlMatcherFactory
30588            *
30589            * @description
30590            * Sets the default behavior when generating or matching URLs with default parameter values.
30591            *
30592            * @param {string} value A string that defines the default parameter URL squashing behavior.
30593            *    `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL
30594            *    `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the
30595            *             parameter is surrounded by slashes, squash (remove) one slash from the URL
30596            *    any other string, e.g. "~": When generating an href with a default parameter value, squash (remove)
30597            *             the parameter value from the URL and replace it with this string.
30598            */
30599           this.defaultSquashPolicy = function(value) {
30600             if (!isDefined(value)) return defaultSquashPolicy;
30601             if (value !== true && value !== false && !isString(value))
30602               throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string");
30603             defaultSquashPolicy = value;
30604             return value;
30605           };
30606
30607           /**
30608            * @ngdoc function
30609            * @name ui.router.util.$urlMatcherFactory#compile
30610            * @methodOf ui.router.util.$urlMatcherFactory
30611            *
30612            * @description
30613            * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern.
30614            *
30615            * @param {string} pattern  The URL pattern.
30616            * @param {Object} config  The config object hash.
30617            * @returns {UrlMatcher}  The UrlMatcher.
30618            */
30619           this.compile = function (pattern, config) {
30620             return new UrlMatcher(pattern, extend(getDefaultConfig(), config));
30621           };
30622
30623           /**
30624            * @ngdoc function
30625            * @name ui.router.util.$urlMatcherFactory#isMatcher
30626            * @methodOf ui.router.util.$urlMatcherFactory
30627            *
30628            * @description
30629            * Returns true if the specified object is a `UrlMatcher`, or false otherwise.
30630            *
30631            * @param {Object} object  The object to perform the type check against.
30632            * @returns {Boolean}  Returns `true` if the object matches the `UrlMatcher` interface, by
30633            *          implementing all the same methods.
30634            */
30635           this.isMatcher = function (o) {
30636             if (!isObject(o)) return false;
30637             var result = true;
30638
30639             forEach(UrlMatcher.prototype, function(val, name) {
30640               if (isFunction(val)) {
30641                 result = result && (isDefined(o[name]) && isFunction(o[name]));
30642               }
30643             });
30644             return result;
30645           };
30646
30647           /**
30648            * @ngdoc function
30649            * @name ui.router.util.$urlMatcherFactory#type
30650            * @methodOf ui.router.util.$urlMatcherFactory
30651            *
30652            * @description
30653            * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to
30654            * generate URLs with typed parameters.
30655            *
30656            * @param {string} name  The type name.
30657            * @param {Object|Function} definition   The type definition. See
30658            *        {@link ui.router.util.type:Type `Type`} for information on the values accepted.
30659            * @param {Object|Function} definitionFn (optional) A function that is injected before the app
30660            *        runtime starts.  The result of this function is merged into the existing `definition`.
30661            *        See {@link ui.router.util.type:Type `Type`} for information on the values accepted.
30662            *
30663            * @returns {Object}  Returns `$urlMatcherFactoryProvider`.
30664            *
30665            * @example
30666            * This is a simple example of a custom type that encodes and decodes items from an
30667            * array, using the array index as the URL-encoded value:
30668            *
30669            * <pre>
30670            * var list = ['John', 'Paul', 'George', 'Ringo'];
30671            *
30672            * $urlMatcherFactoryProvider.type('listItem', {
30673            *   encode: function(item) {
30674            *     // Represent the list item in the URL using its corresponding index
30675            *     return list.indexOf(item);
30676            *   },
30677            *   decode: function(item) {
30678            *     // Look up the list item by index
30679            *     return list[parseInt(item, 10)];
30680            *   },
30681            *   is: function(item) {
30682            *     // Ensure the item is valid by checking to see that it appears
30683            *     // in the list
30684            *     return list.indexOf(item) > -1;
30685            *   }
30686            * });
30687            *
30688            * $stateProvider.state('list', {
30689            *   url: "/list/{item:listItem}",
30690            *   controller: function($scope, $stateParams) {
30691            *     console.log($stateParams.item);
30692            *   }
30693            * });
30694            *
30695            * // ...
30696            *
30697            * // Changes URL to '/list/3', logs "Ringo" to the console
30698            * $state.go('list', { item: "Ringo" });
30699            * </pre>
30700            *
30701            * This is a more complex example of a type that relies on dependency injection to
30702            * interact with services, and uses the parameter name from the URL to infer how to
30703            * handle encoding and decoding parameter values:
30704            *
30705            * <pre>
30706            * // Defines a custom type that gets a value from a service,
30707            * // where each service gets different types of values from
30708            * // a backend API:
30709            * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
30710            *
30711            *   // Matches up services to URL parameter names
30712            *   var services = {
30713            *     user: Users,
30714            *     post: Posts
30715            *   };
30716            *
30717            *   return {
30718            *     encode: function(object) {
30719            *       // Represent the object in the URL using its unique ID
30720            *       return object.id;
30721            *     },
30722            *     decode: function(value, key) {
30723            *       // Look up the object by ID, using the parameter
30724            *       // name (key) to call the correct service
30725            *       return services[key].findById(value);
30726            *     },
30727            *     is: function(object, key) {
30728            *       // Check that object is a valid dbObject
30729            *       return angular.isObject(object) && object.id && services[key];
30730            *     }
30731            *     equals: function(a, b) {
30732            *       // Check the equality of decoded objects by comparing
30733            *       // their unique IDs
30734            *       return a.id === b.id;
30735            *     }
30736            *   };
30737            * });
30738            *
30739            * // In a config() block, you can then attach URLs with
30740            * // type-annotated parameters:
30741            * $stateProvider.state('users', {
30742            *   url: "/users",
30743            *   // ...
30744            * }).state('users.item', {
30745            *   url: "/{user:dbObject}",
30746            *   controller: function($scope, $stateParams) {
30747            *     // $stateParams.user will now be an object returned from
30748            *     // the Users service
30749            *   },
30750            *   // ...
30751            * });
30752            * </pre>
30753            */
30754           this.type = function (name, definition, definitionFn) {
30755             if (!isDefined(definition)) return $types[name];
30756             if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined.");
30757
30758             $types[name] = new Type(extend({ name: name }, definition));
30759             if (definitionFn) {
30760               typeQueue.push({ name: name, def: definitionFn });
30761               if (!enqueue) flushTypeQueue();
30762             }
30763             return this;
30764           };
30765
30766           // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s
30767           function flushTypeQueue() {
30768             while(typeQueue.length) {
30769               var type = typeQueue.shift();
30770               if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime.");
30771               angular.extend($types[type.name], injector.invoke(type.def));
30772             }
30773           }
30774
30775           // Register default types. Store them in the prototype of $types.
30776           forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); });
30777           $types = inherit($types, {});
30778
30779           /* No need to document $get, since it returns this */
30780           this.$get = ['$injector', function ($injector) {
30781             injector = $injector;
30782             enqueue = false;
30783             flushTypeQueue();
30784
30785             forEach(defaultTypes, function(type, name) {
30786               if (!$types[name]) $types[name] = new Type(type);
30787             });
30788             return this;
30789           }];
30790
30791           this.Param = function Param(id, type, config, location) {
30792             var self = this;
30793             config = unwrapShorthand(config);
30794             type = getType(config, type, location);
30795             var arrayMode = getArrayMode();
30796             type = arrayMode ? type.$asArray(arrayMode, location === "search") : type;
30797             if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined)
30798               config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to ""
30799             var isOptional = config.value !== undefined;
30800             var squash = getSquashPolicy(config, isOptional);
30801             var replace = getReplace(config, arrayMode, isOptional, squash);
30802
30803             function unwrapShorthand(config) {
30804               var keys = isObject(config) ? objectKeys(config) : [];
30805               var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 &&
30806                                 indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1;
30807               if (isShorthand) config = { value: config };
30808               config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; };
30809               return config;
30810             }
30811
30812             function getType(config, urlType, location) {
30813               if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations.");
30814               if (urlType) return urlType;
30815               if (!config.type) return (location === "config" ? $types.any : $types.string);
30816 <<<<<<< HEAD
30817
30818               if (angular.isString(config.type))
30819                 return $types[config.type];
30820               if (config.type instanceof Type)
30821                 return config.type;
30822               return new Type(config.type);
30823 =======
30824               return config.type instanceof Type ? config.type : new Type(config.type);
30825 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
30826             }
30827
30828             // array config: param name (param[]) overrides default settings.  explicit config overrides param name.
30829             function getArrayMode() {
30830               var arrayDefaults = { array: (location === "search" ? "auto" : false) };
30831               var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {};
30832               return extend(arrayDefaults, arrayParamNomenclature, config).array;
30833             }
30834
30835             /**
30836              * returns false, true, or the squash value to indicate the "default parameter url squash policy".
30837              */
30838             function getSquashPolicy(config, isOptional) {
30839               var squash = config.squash;
30840               if (!isOptional || squash === false) return false;
30841               if (!isDefined(squash) || squash == null) return defaultSquashPolicy;
30842               if (squash === true || isString(squash)) return squash;
30843               throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string");
30844             }
30845
30846             function getReplace(config, arrayMode, isOptional, squash) {
30847               var replace, configuredKeys, defaultPolicy = [
30848                 { from: "",   to: (isOptional || arrayMode ? undefined : "") },
30849                 { from: null, to: (isOptional || arrayMode ? undefined : "") }
30850               ];
30851               replace = isArray(config.replace) ? config.replace : [];
30852               if (isString(squash))
30853                 replace.push({ from: squash, to: undefined });
30854               configuredKeys = map(replace, function(item) { return item.from; } );
30855               return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace);
30856             }
30857
30858             /**
30859              * [Internal] Get the default value of a parameter, which may be an injectable function.
30860              */
30861             function $$getDefaultValue() {
30862               if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
30863               var defaultValue = injector.invoke(config.$$fn);
30864               if (defaultValue !== null && defaultValue !== undefined && !self.type.is(defaultValue))
30865                 throw new Error("Default value (" + defaultValue + ") for parameter '" + self.id + "' is not an instance of Type (" + self.type.name + ")");
30866               return defaultValue;
30867             }
30868
30869             /**
30870              * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the
30871              * default value, which may be the result of an injectable function.
30872              */
30873             function $value(value) {
30874               function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; }
30875               function $replace(value) {
30876                 var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; });
30877                 return replacement.length ? replacement[0] : value;
30878               }
30879               value = $replace(value);
30880               return !isDefined(value) ? $$getDefaultValue() : self.type.$normalize(value);
30881             }
30882
30883             function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; }
30884
30885             extend(this, {
30886               id: id,
30887               type: type,
30888               location: location,
30889               array: arrayMode,
30890               squash: squash,
30891               replace: replace,
30892               isOptional: isOptional,
30893               value: $value,
30894               dynamic: undefined,
30895               config: config,
30896               toString: toString
30897             });
30898           };
30899
30900           function ParamSet(params) {
30901             extend(this, params || {});
30902           }
30903
30904           ParamSet.prototype = {
30905             $$new: function() {
30906               return inherit(this, extend(new ParamSet(), { $$parent: this}));
30907             },
30908             $$keys: function () {
30909               var keys = [], chain = [], parent = this,
30910                 ignore = objectKeys(ParamSet.prototype);
30911               while (parent) { chain.push(parent); parent = parent.$$parent; }
30912               chain.reverse();
30913               forEach(chain, function(paramset) {
30914                 forEach(objectKeys(paramset), function(key) {
30915                     if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key);
30916                 });
30917               });
30918               return keys;
30919             },
30920             $$values: function(paramValues) {
30921               var values = {}, self = this;
30922               forEach(self.$$keys(), function(key) {
30923                 values[key] = self[key].value(paramValues && paramValues[key]);
30924               });
30925               return values;
30926             },
30927             $$equals: function(paramValues1, paramValues2) {
30928               var equal = true, self = this;
30929               forEach(self.$$keys(), function(key) {
30930                 var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key];
30931                 if (!self[key].type.equals(left, right)) equal = false;
30932               });
30933               return equal;
30934             },
30935             $$validates: function $$validate(paramValues) {
30936               var keys = this.$$keys(), i, param, rawVal, normalized, encoded;
30937               for (i = 0; i < keys.length; i++) {
30938                 param = this[keys[i]];
30939                 rawVal = paramValues[keys[i]];
30940                 if ((rawVal === undefined || rawVal === null) && param.isOptional)
30941                   break; // There was no parameter value, but the param is optional
30942                 normalized = param.type.$normalize(rawVal);
30943                 if (!param.type.is(normalized))
30944                   return false; // The value was not of the correct Type, and could not be decoded to the correct Type
30945                 encoded = param.type.encode(normalized);
30946                 if (angular.isString(encoded) && !param.type.pattern.exec(encoded))
30947                   return false; // The value was of the correct type, but when encoded, did not match the Type's regexp
30948               }
30949               return true;
30950             },
30951             $$parent: undefined
30952           };
30953
30954           this.ParamSet = ParamSet;
30955         }
30956
30957         // Register as a provider so it's available to other providers
30958         angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory);
30959         angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]);
30960
30961         /**
30962          * @ngdoc object
30963          * @name ui.router.router.$urlRouterProvider
30964          *
30965          * @requires ui.router.util.$urlMatcherFactoryProvider
30966          * @requires $locationProvider
30967          *
30968          * @description
30969          * `$urlRouterProvider` has the responsibility of watching `$location`. 
30970          * When `$location` changes it runs through a list of rules one by one until a 
30971          * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify 
30972          * a url in a state configuration. All urls are compiled into a UrlMatcher object.
30973          *
30974          * There are several methods on `$urlRouterProvider` that make it useful to use directly
30975          * in your module config.
30976          */
30977         $UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider'];
30978         function $UrlRouterProvider(   $locationProvider,   $urlMatcherFactory) {
30979           var rules = [], otherwise = null, interceptDeferred = false, listener;
30980
30981           // Returns a string that is a prefix of all strings matching the RegExp
30982           function regExpPrefix(re) {
30983             var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source);
30984             return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : '';
30985           }
30986
30987           // Interpolates matched values into a String.replace()-style pattern
30988           function interpolate(pattern, match) {
30989             return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) {
30990               return match[what === '$' ? 0 : Number(what)];
30991             });
30992           }
30993
30994           /**
30995            * @ngdoc function
30996            * @name ui.router.router.$urlRouterProvider#rule
30997            * @methodOf ui.router.router.$urlRouterProvider
30998            *
30999            * @description
31000            * Defines rules that are used by `$urlRouterProvider` to find matches for
31001            * specific URLs.
31002            *
31003            * @example
31004            * <pre>
31005            * var app = angular.module('app', ['ui.router.router']);
31006            *
31007            * app.config(function ($urlRouterProvider) {
31008            *   // Here's an example of how you might allow case insensitive urls
31009            *   $urlRouterProvider.rule(function ($injector, $location) {
31010            *     var path = $location.path(),
31011            *         normalized = path.toLowerCase();
31012            *
31013            *     if (path !== normalized) {
31014            *       return normalized;
31015            *     }
31016            *   });
31017            * });
31018            * </pre>
31019            *
31020 <<<<<<< HEAD
31021            * @param {function} rule Handler function that takes `$injector` and `$location`
31022 =======
31023            * @param {object} rule Handler function that takes `$injector` and `$location`
31024 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31025            * services as arguments. You can use them to return a valid path as a string.
31026            *
31027            * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
31028            */
31029           this.rule = function (rule) {
31030             if (!isFunction(rule)) throw new Error("'rule' must be a function");
31031             rules.push(rule);
31032             return this;
31033           };
31034
31035           /**
31036            * @ngdoc object
31037            * @name ui.router.router.$urlRouterProvider#otherwise
31038            * @methodOf ui.router.router.$urlRouterProvider
31039            *
31040            * @description
31041            * Defines a path that is used when an invalid route is requested.
31042            *
31043            * @example
31044            * <pre>
31045            * var app = angular.module('app', ['ui.router.router']);
31046            *
31047            * app.config(function ($urlRouterProvider) {
31048            *   // if the path doesn't match any of the urls you configured
31049            *   // otherwise will take care of routing the user to the
31050            *   // specified url
31051            *   $urlRouterProvider.otherwise('/index');
31052            *
31053            *   // Example of using function rule as param
31054            *   $urlRouterProvider.otherwise(function ($injector, $location) {
31055            *     return '/a/valid/url';
31056            *   });
31057            * });
31058            * </pre>
31059            *
31060 <<<<<<< HEAD
31061            * @param {string|function} rule The url path you want to redirect to or a function 
31062 =======
31063            * @param {string|object} rule The url path you want to redirect to or a function 
31064 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31065            * rule that returns the url path. The function version is passed two params: 
31066            * `$injector` and `$location` services, and must return a url string.
31067            *
31068            * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
31069            */
31070           this.otherwise = function (rule) {
31071             if (isString(rule)) {
31072               var redirect = rule;
31073               rule = function () { return redirect; };
31074             }
31075             else if (!isFunction(rule)) throw new Error("'rule' must be a function");
31076             otherwise = rule;
31077             return this;
31078           };
31079
31080
31081           function handleIfMatch($injector, handler, match) {
31082             if (!match) return false;
31083             var result = $injector.invoke(handler, handler, { $match: match });
31084             return isDefined(result) ? result : true;
31085           }
31086
31087           /**
31088            * @ngdoc function
31089            * @name ui.router.router.$urlRouterProvider#when
31090            * @methodOf ui.router.router.$urlRouterProvider
31091            *
31092            * @description
31093 <<<<<<< HEAD
31094            * Registers a handler for a given url matching. 
31095            * 
31096            * If the handler is a string, it is
31097 =======
31098            * Registers a handler for a given url matching. if handle is a string, it is
31099 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31100            * treated as a redirect, and is interpolated according to the syntax of match
31101            * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise).
31102            *
31103            * If the handler is a function, it is injectable. It gets invoked if `$location`
31104            * matches. You have the option of inject the match object as `$match`.
31105            *
31106            * The handler can return
31107            *
31108            * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`
31109            *   will continue trying to find another one that matches.
31110            * - **string** which is treated as a redirect and passed to `$location.url()`
31111            * - **void** or any **truthy** value tells `$urlRouter` that the url was handled.
31112            *
31113            * @example
31114            * <pre>
31115            * var app = angular.module('app', ['ui.router.router']);
31116            *
31117            * app.config(function ($urlRouterProvider) {
31118            *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
31119            *     if ($state.$current.navigable !== state ||
31120            *         !equalForKeys($match, $stateParams) {
31121            *      $state.transitionTo(state, $match, false);
31122            *     }
31123            *   });
31124            * });
31125            * </pre>
31126            *
31127            * @param {string|object} what The incoming path that you want to redirect.
31128 <<<<<<< HEAD
31129            * @param {string|function} handler The path you want to redirect your user to.
31130 =======
31131            * @param {string|object} handler The path you want to redirect your user to.
31132 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31133            */
31134           this.when = function (what, handler) {
31135             var redirect, handlerIsString = isString(handler);
31136             if (isString(what)) what = $urlMatcherFactory.compile(what);
31137
31138             if (!handlerIsString && !isFunction(handler) && !isArray(handler))
31139               throw new Error("invalid 'handler' in when()");
31140
31141             var strategies = {
31142               matcher: function (what, handler) {
31143                 if (handlerIsString) {
31144                   redirect = $urlMatcherFactory.compile(handler);
31145                   handler = ['$match', function ($match) { return redirect.format($match); }];
31146                 }
31147                 return extend(function ($injector, $location) {
31148                   return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));
31149                 }, {
31150                   prefix: isString(what.prefix) ? what.prefix : ''
31151                 });
31152               },
31153               regex: function (what, handler) {
31154                 if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky");
31155
31156                 if (handlerIsString) {
31157                   redirect = handler;
31158                   handler = ['$match', function ($match) { return interpolate(redirect, $match); }];
31159                 }
31160                 return extend(function ($injector, $location) {
31161                   return handleIfMatch($injector, handler, what.exec($location.path()));
31162                 }, {
31163                   prefix: regExpPrefix(what)
31164                 });
31165               }
31166             };
31167
31168             var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp };
31169
31170             for (var n in check) {
31171               if (check[n]) return this.rule(strategies[n](what, handler));
31172             }
31173
31174             throw new Error("invalid 'what' in when()");
31175           };
31176
31177           /**
31178            * @ngdoc function
31179            * @name ui.router.router.$urlRouterProvider#deferIntercept
31180            * @methodOf ui.router.router.$urlRouterProvider
31181            *
31182            * @description
31183            * Disables (or enables) deferring location change interception.
31184            *
31185            * If you wish to customize the behavior of syncing the URL (for example, if you wish to
31186            * defer a transition but maintain the current URL), call this method at configuration time.
31187            * Then, at run time, call `$urlRouter.listen()` after you have configured your own
31188            * `$locationChangeSuccess` event handler.
31189            *
31190            * @example
31191            * <pre>
31192            * var app = angular.module('app', ['ui.router.router']);
31193            *
31194            * app.config(function ($urlRouterProvider) {
31195            *
31196            *   // Prevent $urlRouter from automatically intercepting URL changes;
31197            *   // this allows you to configure custom behavior in between
31198            *   // location changes and route synchronization:
31199            *   $urlRouterProvider.deferIntercept();
31200            *
31201            * }).run(function ($rootScope, $urlRouter, UserService) {
31202            *
31203            *   $rootScope.$on('$locationChangeSuccess', function(e) {
31204            *     // UserService is an example service for managing user state
31205            *     if (UserService.isLoggedIn()) return;
31206            *
31207            *     // Prevent $urlRouter's default handler from firing
31208            *     e.preventDefault();
31209            *
31210            *     UserService.handleLogin().then(function() {
31211            *       // Once the user has logged in, sync the current URL
31212            *       // to the router:
31213            *       $urlRouter.sync();
31214            *     });
31215            *   });
31216            *
31217            *   // Configures $urlRouter's listener *after* your custom listener
31218            *   $urlRouter.listen();
31219            * });
31220            * </pre>
31221            *
31222            * @param {boolean} defer Indicates whether to defer location change interception. Passing
31223                     no parameter is equivalent to `true`.
31224            */
31225           this.deferIntercept = function (defer) {
31226             if (defer === undefined) defer = true;
31227             interceptDeferred = defer;
31228           };
31229
31230           /**
31231            * @ngdoc object
31232            * @name ui.router.router.$urlRouter
31233            *
31234            * @requires $location
31235            * @requires $rootScope
31236            * @requires $injector
31237            * @requires $browser
31238            *
31239            * @description
31240            *
31241            */
31242           this.$get = $get;
31243 <<<<<<< HEAD
31244           $get.$inject = ['$location', '$rootScope', '$injector', '$browser', '$sniffer'];
31245           function $get(   $location,   $rootScope,   $injector,   $browser,   $sniffer) {
31246 =======
31247           $get.$inject = ['$location', '$rootScope', '$injector', '$browser'];
31248           function $get(   $location,   $rootScope,   $injector,   $browser) {
31249 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31250
31251             var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl;
31252
31253             function appendBasePath(url, isHtml5, absolute) {
31254               if (baseHref === '/') return url;
31255               if (isHtml5) return baseHref.slice(0, -1) + url;
31256               if (absolute) return baseHref.slice(1) + url;
31257               return url;
31258             }
31259
31260             // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree
31261             function update(evt) {
31262               if (evt && evt.defaultPrevented) return;
31263               var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl;
31264               lastPushedUrl = undefined;
31265               // TODO: Re-implement this in 1.0 for https://github.com/angular-ui/ui-router/issues/1573
31266               //if (ignoreUpdate) return true;
31267
31268               function check(rule) {
31269                 var handled = rule($injector, $location);
31270
31271                 if (!handled) return false;
31272                 if (isString(handled)) $location.replace().url(handled);
31273                 return true;
31274               }
31275               var n = rules.length, i;
31276
31277               for (i = 0; i < n; i++) {
31278                 if (check(rules[i])) return;
31279               }
31280               // always check otherwise last to allow dynamic updates to the set of rules
31281               if (otherwise) check(otherwise);
31282             }
31283
31284             function listen() {
31285               listener = listener || $rootScope.$on('$locationChangeSuccess', update);
31286               return listener;
31287             }
31288
31289             if (!interceptDeferred) listen();
31290
31291             return {
31292               /**
31293                * @ngdoc function
31294                * @name ui.router.router.$urlRouter#sync
31295                * @methodOf ui.router.router.$urlRouter
31296                *
31297                * @description
31298                * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`.
31299                * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event,
31300                * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed
31301                * with the transition by calling `$urlRouter.sync()`.
31302                *
31303                * @example
31304                * <pre>
31305                * angular.module('app', ['ui.router'])
31306                *   .run(function($rootScope, $urlRouter) {
31307                *     $rootScope.$on('$locationChangeSuccess', function(evt) {
31308                *       // Halt state change from even starting
31309                *       evt.preventDefault();
31310                *       // Perform custom logic
31311                *       var meetsRequirement = ...
31312                *       // Continue with the update and state transition if logic allows
31313                *       if (meetsRequirement) $urlRouter.sync();
31314                *     });
31315                * });
31316                * </pre>
31317                */
31318               sync: function() {
31319                 update();
31320               },
31321
31322               listen: function() {
31323                 return listen();
31324               },
31325
31326               update: function(read) {
31327                 if (read) {
31328                   location = $location.url();
31329                   return;
31330                 }
31331                 if ($location.url() === location) return;
31332
31333                 $location.url(location);
31334                 $location.replace();
31335               },
31336
31337               push: function(urlMatcher, params, options) {
31338                  var url = urlMatcher.format(params || {});
31339
31340                 // Handle the special hash param, if needed
31341                 if (url !== null && params && params['#']) {
31342                     url += '#' + params['#'];
31343                 }
31344
31345                 $location.url(url);
31346                 lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined;
31347                 if (options && options.replace) $location.replace();
31348               },
31349
31350               /**
31351                * @ngdoc function
31352                * @name ui.router.router.$urlRouter#href
31353                * @methodOf ui.router.router.$urlRouter
31354                *
31355                * @description
31356                * A URL generation method that returns the compiled URL for a given
31357                * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters.
31358                *
31359                * @example
31360                * <pre>
31361                * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
31362                *   person: "bob"
31363                * });
31364                * // $bob == "/about/bob";
31365                * </pre>
31366                *
31367                * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate.
31368                * @param {object=} params An object of parameter values to fill the matcher's required parameters.
31369                * @param {object=} options Options object. The options are:
31370                *
31371                * - **`absolute`** - {boolean=false},  If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
31372                *
31373                * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher`
31374                */
31375               href: function(urlMatcher, params, options) {
31376                 if (!urlMatcher.validates(params)) return null;
31377
31378                 var isHtml5 = $locationProvider.html5Mode();
31379                 if (angular.isObject(isHtml5)) {
31380                   isHtml5 = isHtml5.enabled;
31381                 }
31382 <<<<<<< HEAD
31383
31384                 isHtml5 = isHtml5 && $sniffer.history;
31385 =======
31386 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31387                 
31388                 var url = urlMatcher.format(params);
31389                 options = options || {};
31390
31391                 if (!isHtml5 && url !== null) {
31392                   url = "#" + $locationProvider.hashPrefix() + url;
31393                 }
31394
31395                 // Handle special hash param, if needed
31396                 if (url !== null && params && params['#']) {
31397                   url += '#' + params['#'];
31398                 }
31399
31400                 url = appendBasePath(url, isHtml5, options.absolute);
31401
31402                 if (!options.absolute || !url) {
31403                   return url;
31404                 }
31405
31406                 var slash = (!isHtml5 && url ? '/' : ''), port = $location.port();
31407                 port = (port === 80 || port === 443 ? '' : ':' + port);
31408
31409                 return [$location.protocol(), '://', $location.host(), port, slash, url].join('');
31410               }
31411             };
31412           }
31413         }
31414
31415         angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);
31416
31417         /**
31418          * @ngdoc object
31419          * @name ui.router.state.$stateProvider
31420          *
31421          * @requires ui.router.router.$urlRouterProvider
31422          * @requires ui.router.util.$urlMatcherFactoryProvider
31423          *
31424          * @description
31425          * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely
31426          * on state.
31427          *
31428          * A state corresponds to a "place" in the application in terms of the overall UI and
31429          * navigation. A state describes (via the controller / template / view properties) what
31430          * the UI looks like and does at that place.
31431          *
31432          * States often have things in common, and the primary way of factoring out these
31433          * commonalities in this model is via the state hierarchy, i.e. parent/child states aka
31434          * nested states.
31435          *
31436          * The `$stateProvider` provides interfaces to declare these states for your app.
31437          */
31438         $StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider'];
31439         function $StateProvider(   $urlRouterProvider,   $urlMatcherFactory) {
31440
31441           var root, states = {}, $state, queue = {}, abstractKey = 'abstract';
31442
31443           // Builds state properties from definition passed to registerState()
31444           var stateBuilder = {
31445
31446             // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined.
31447             // state.children = [];
31448             // if (parent) parent.children.push(state);
31449             parent: function(state) {
31450               if (isDefined(state.parent) && state.parent) return findState(state.parent);
31451               // regex matches any valid composite state name
31452               // would match "contact.list" but not "contacts"
31453               var compositeName = /^(.+)\.[^.]+$/.exec(state.name);
31454               return compositeName ? findState(compositeName[1]) : root;
31455             },
31456
31457             // inherit 'data' from parent and override by own values (if any)
31458             data: function(state) {
31459               if (state.parent && state.parent.data) {
31460 <<<<<<< HEAD
31461                 state.data = state.self.data = inherit(state.parent.data, state.data);
31462 =======
31463                 state.data = state.self.data = extend({}, state.parent.data, state.data);
31464 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31465               }
31466               return state.data;
31467             },
31468
31469             // Build a URLMatcher if necessary, either via a relative or absolute URL
31470             url: function(state) {
31471               var url = state.url, config = { params: state.params || {} };
31472
31473               if (isString(url)) {
31474                 if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config);
31475                 return (state.parent.navigable || root).url.concat(url, config);
31476               }
31477
31478               if (!url || $urlMatcherFactory.isMatcher(url)) return url;
31479               throw new Error("Invalid url '" + url + "' in state '" + state + "'");
31480             },
31481
31482             // Keep track of the closest ancestor state that has a URL (i.e. is navigable)
31483             navigable: function(state) {
31484               return state.url ? state : (state.parent ? state.parent.navigable : null);
31485             },
31486
31487             // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params
31488             ownParams: function(state) {
31489               var params = state.url && state.url.params || new $$UMFP.ParamSet();
31490               forEach(state.params || {}, function(config, id) {
31491                 if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config");
31492               });
31493               return params;
31494             },
31495
31496             // Derive parameters for this state and ensure they're a super-set of parent's parameters
31497             params: function(state) {
31498 <<<<<<< HEAD
31499               var ownParams = pick(state.ownParams, state.ownParams.$$keys());
31500               return state.parent && state.parent.params ? extend(state.parent.params.$$new(), ownParams) : new $$UMFP.ParamSet();
31501 =======
31502               return state.parent && state.parent.params ? extend(state.parent.params.$$new(), state.ownParams) : new $$UMFP.ParamSet();
31503 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31504             },
31505
31506             // If there is no explicit multi-view configuration, make one up so we don't have
31507             // to handle both cases in the view directive later. Note that having an explicit
31508             // 'views' property will mean the default unnamed view properties are ignored. This
31509             // is also a good time to resolve view names to absolute names, so everything is a
31510             // straight lookup at link time.
31511             views: function(state) {
31512               var views = {};
31513
31514               forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) {
31515                 if (name.indexOf('@') < 0) name += '@' + state.parent.name;
31516                 views[name] = view;
31517               });
31518               return views;
31519             },
31520
31521             // Keep a full path from the root down to this state as this is needed for state activation.
31522             path: function(state) {
31523               return state.parent ? state.parent.path.concat(state) : []; // exclude root from path
31524             },
31525
31526             // Speed up $state.contains() as it's used a lot
31527             includes: function(state) {
31528               var includes = state.parent ? extend({}, state.parent.includes) : {};
31529               includes[state.name] = true;
31530               return includes;
31531             },
31532
31533             $delegates: {}
31534           };
31535
31536           function isRelative(stateName) {
31537             return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0;
31538           }
31539
31540           function findState(stateOrName, base) {
31541             if (!stateOrName) return undefined;
31542
31543             var isStr = isString(stateOrName),
31544                 name  = isStr ? stateOrName : stateOrName.name,
31545                 path  = isRelative(name);
31546
31547             if (path) {
31548               if (!base) throw new Error("No reference point given for path '"  + name + "'");
31549               base = findState(base);
31550               
31551               var rel = name.split("."), i = 0, pathLength = rel.length, current = base;
31552
31553               for (; i < pathLength; i++) {
31554                 if (rel[i] === "" && i === 0) {
31555                   current = base;
31556                   continue;
31557                 }
31558                 if (rel[i] === "^") {
31559                   if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'");
31560                   current = current.parent;
31561                   continue;
31562                 }
31563                 break;
31564               }
31565               rel = rel.slice(i).join(".");
31566               name = current.name + (current.name && rel ? "." : "") + rel;
31567             }
31568             var state = states[name];
31569
31570             if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) {
31571               return state;
31572             }
31573             return undefined;
31574           }
31575
31576           function queueState(parentName, state) {
31577             if (!queue[parentName]) {
31578               queue[parentName] = [];
31579             }
31580             queue[parentName].push(state);
31581           }
31582
31583           function flushQueuedChildren(parentName) {
31584             var queued = queue[parentName] || [];
31585             while(queued.length) {
31586               registerState(queued.shift());
31587             }
31588           }
31589
31590           function registerState(state) {
31591             // Wrap a new object around the state so we can store our private details easily.
31592             state = inherit(state, {
31593               self: state,
31594               resolve: state.resolve || {},
31595               toString: function() { return this.name; }
31596             });
31597
31598             var name = state.name;
31599             if (!isString(name) || name.indexOf('@') >= 0) throw new Error("State must have a valid name");
31600 <<<<<<< HEAD
31601             if (states.hasOwnProperty(name)) throw new Error("State '" + name + "' is already defined");
31602 =======
31603             if (states.hasOwnProperty(name)) throw new Error("State '" + name + "'' is already defined");
31604 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31605
31606             // Get parent name
31607             var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.'))
31608                 : (isString(state.parent)) ? state.parent
31609                 : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name
31610                 : '';
31611
31612             // If parent is not registered yet, add state to queue and register later
31613             if (parentName && !states[parentName]) {
31614               return queueState(parentName, state.self);
31615             }
31616
31617             for (var key in stateBuilder) {
31618               if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]);
31619             }
31620             states[name] = state;
31621
31622             // Register the state in the global state list and with $urlRouter if necessary.
31623             if (!state[abstractKey] && state.url) {
31624               $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {
31625                 if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {
31626                   $state.transitionTo(state, $match, { inherit: true, location: false });
31627                 }
31628               }]);
31629             }
31630
31631             // Register any queued children
31632             flushQueuedChildren(name);
31633
31634             return state;
31635           }
31636
31637           // Checks text to see if it looks like a glob.
31638           function isGlob (text) {
31639             return text.indexOf('*') > -1;
31640           }
31641
31642           // Returns true if glob matches current $state name.
31643           function doesStateMatchGlob (glob) {
31644             var globSegments = glob.split('.'),
31645                 segments = $state.$current.name.split('.');
31646
31647             //match single stars
31648             for (var i = 0, l = globSegments.length; i < l; i++) {
31649               if (globSegments[i] === '*') {
31650                 segments[i] = '*';
31651               }
31652             }
31653
31654             //match greedy starts
31655             if (globSegments[0] === '**') {
31656                segments = segments.slice(indexOf(segments, globSegments[1]));
31657                segments.unshift('**');
31658             }
31659             //match greedy ends
31660             if (globSegments[globSegments.length - 1] === '**') {
31661                segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE);
31662                segments.push('**');
31663             }
31664
31665             if (globSegments.length != segments.length) {
31666               return false;
31667             }
31668
31669             return segments.join('') === globSegments.join('');
31670           }
31671
31672
31673           // Implicit root state that is always active
31674           root = registerState({
31675             name: '',
31676             url: '^',
31677             views: null,
31678             'abstract': true
31679           });
31680           root.navigable = null;
31681
31682
31683           /**
31684            * @ngdoc function
31685            * @name ui.router.state.$stateProvider#decorator
31686            * @methodOf ui.router.state.$stateProvider
31687            *
31688            * @description
31689            * Allows you to extend (carefully) or override (at your own peril) the 
31690            * `stateBuilder` object used internally by `$stateProvider`. This can be used 
31691            * to add custom functionality to ui-router, for example inferring templateUrl 
31692            * based on the state name.
31693            *
31694            * When passing only a name, it returns the current (original or decorated) builder
31695            * function that matches `name`.
31696            *
31697            * The builder functions that can be decorated are listed below. Though not all
31698            * necessarily have a good use case for decoration, that is up to you to decide.
31699            *
31700            * In addition, users can attach custom decorators, which will generate new 
31701            * properties within the state's internal definition. There is currently no clear 
31702            * use-case for this beyond accessing internal states (i.e. $state.$current), 
31703            * however, expect this to become increasingly relevant as we introduce additional 
31704            * meta-programming features.
31705            *
31706            * **Warning**: Decorators should not be interdependent because the order of 
31707            * execution of the builder functions in non-deterministic. Builder functions 
31708            * should only be dependent on the state definition object and super function.
31709            *
31710            *
31711            * Existing builder functions and current return values:
31712            *
31713            * - **parent** `{object}` - returns the parent state object.
31714            * - **data** `{object}` - returns state data, including any inherited data that is not
31715            *   overridden by own values (if any).
31716            * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}
31717            *   or `null`.
31718            * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is 
31719            *   navigable).
31720            * - **params** `{object}` - returns an array of state params that are ensured to 
31721            *   be a super-set of parent's params.
31722            * - **views** `{object}` - returns a views object where each key is an absolute view 
31723            *   name (i.e. "viewName@stateName") and each value is the config object 
31724            *   (template, controller) for the view. Even when you don't use the views object 
31725            *   explicitly on a state config, one is still created for you internally.
31726            *   So by decorating this builder function you have access to decorating template 
31727            *   and controller properties.
31728            * - **ownParams** `{object}` - returns an array of params that belong to the state, 
31729            *   not including any params defined by ancestor states.
31730            * - **path** `{string}` - returns the full path from the root down to this state. 
31731            *   Needed for state activation.
31732            * - **includes** `{object}` - returns an object that includes every state that 
31733            *   would pass a `$state.includes()` test.
31734            *
31735            * @example
31736            * <pre>
31737            * // Override the internal 'views' builder with a function that takes the state
31738            * // definition, and a reference to the internal function being overridden:
31739            * $stateProvider.decorator('views', function (state, parent) {
31740            *   var result = {},
31741            *       views = parent(state);
31742            *
31743            *   angular.forEach(views, function (config, name) {
31744            *     var autoName = (state.name + '.' + name).replace('.', '/');
31745            *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
31746            *     result[name] = config;
31747            *   });
31748            *   return result;
31749            * });
31750            *
31751            * $stateProvider.state('home', {
31752            *   views: {
31753            *     'contact.list': { controller: 'ListController' },
31754            *     'contact.item': { controller: 'ItemController' }
31755            *   }
31756            * });
31757            *
31758            * // ...
31759            *
31760            * $state.go('home');
31761            * // Auto-populates list and item views with /partials/home/contact/list.html,
31762            * // and /partials/home/contact/item.html, respectively.
31763            * </pre>
31764            *
31765            * @param {string} name The name of the builder function to decorate. 
31766            * @param {object} func A function that is responsible for decorating the original 
31767            * builder function. The function receives two parameters:
31768            *
31769            *   - `{object}` - state - The state config object.
31770            *   - `{object}` - super - The original builder function.
31771            *
31772            * @return {object} $stateProvider - $stateProvider instance
31773            */
31774           this.decorator = decorator;
31775           function decorator(name, func) {
31776             /*jshint validthis: true */
31777             if (isString(name) && !isDefined(func)) {
31778               return stateBuilder[name];
31779             }
31780             if (!isFunction(func) || !isString(name)) {
31781               return this;
31782             }
31783             if (stateBuilder[name] && !stateBuilder.$delegates[name]) {
31784               stateBuilder.$delegates[name] = stateBuilder[name];
31785             }
31786             stateBuilder[name] = func;
31787             return this;
31788           }
31789
31790           /**
31791            * @ngdoc function
31792            * @name ui.router.state.$stateProvider#state
31793            * @methodOf ui.router.state.$stateProvider
31794            *
31795            * @description
31796            * Registers a state configuration under a given state name. The stateConfig object
31797            * has the following acceptable properties.
31798            *
31799            * @param {string} name A unique state name, e.g. "home", "about", "contacts".
31800            * To create a parent/child state use a dot, e.g. "about.sales", "home.newest".
31801            * @param {object} stateConfig State configuration object.
31802            * @param {string|function=} stateConfig.template
31803            * <a id='template'></a>
31804            *   html template as a string or a function that returns
31805            *   an html template as a string which should be used by the uiView directives. This property 
31806            *   takes precedence over templateUrl.
31807            *   
31808            *   If `template` is a function, it will be called with the following parameters:
31809            *
31810            *   - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
31811            *     applying the current state
31812            *
31813            * <pre>template:
31814            *   "<h1>inline template definition</h1>" +
31815            *   "<div ui-view></div>"</pre>
31816            * <pre>template: function(params) {
31817            *       return "<h1>generated template</h1>"; }</pre>
31818            * </div>
31819            *
31820            * @param {string|function=} stateConfig.templateUrl
31821            * <a id='templateUrl'></a>
31822            *
31823            *   path or function that returns a path to an html
31824            *   template that should be used by uiView.
31825            *   
31826            *   If `templateUrl` is a function, it will be called with the following parameters:
31827            *
31828            *   - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by 
31829            *     applying the current state
31830            *
31831            * <pre>templateUrl: "home.html"</pre>
31832            * <pre>templateUrl: function(params) {
31833            *     return myTemplates[params.pageId]; }</pre>
31834            *
31835            * @param {function=} stateConfig.templateProvider
31836            * <a id='templateProvider'></a>
31837            *    Provider function that returns HTML content string.
31838            * <pre> templateProvider:
31839            *       function(MyTemplateService, params) {
31840            *         return MyTemplateService.getTemplate(params.pageId);
31841            *       }</pre>
31842            *
31843            * @param {string|function=} stateConfig.controller
31844            * <a id='controller'></a>
31845            *
31846            *  Controller fn that should be associated with newly
31847            *   related scope or the name of a registered controller if passed as a string.
31848            *   Optionally, the ControllerAs may be declared here.
31849            * <pre>controller: "MyRegisteredController"</pre>
31850            * <pre>controller:
31851            *     "MyRegisteredController as fooCtrl"}</pre>
31852            * <pre>controller: function($scope, MyService) {
31853            *     $scope.data = MyService.getData(); }</pre>
31854            *
31855            * @param {function=} stateConfig.controllerProvider
31856            * <a id='controllerProvider'></a>
31857            *
31858            * Injectable provider function that returns the actual controller or string.
31859            * <pre>controllerProvider:
31860            *   function(MyResolveData) {
31861            *     if (MyResolveData.foo)
31862            *       return "FooCtrl"
31863            *     else if (MyResolveData.bar)
31864            *       return "BarCtrl";
31865            *     else return function($scope) {
31866            *       $scope.baz = "Qux";
31867            *     }
31868            *   }</pre>
31869            *
31870            * @param {string=} stateConfig.controllerAs
31871            * <a id='controllerAs'></a>
31872            * 
31873            * A controller alias name. If present the controller will be
31874            *   published to scope under the controllerAs name.
31875            * <pre>controllerAs: "myCtrl"</pre>
31876            *
31877            * @param {string|object=} stateConfig.parent
31878            * <a id='parent'></a>
31879            * Optionally specifies the parent state of this state.
31880            *
31881            * <pre>parent: 'parentState'</pre>
31882            * <pre>parent: parentState // JS variable</pre>
31883            *
31884            * @param {object=} stateConfig.resolve
31885            * <a id='resolve'></a>
31886            *
31887            * An optional map&lt;string, function&gt; of dependencies which
31888            *   should be injected into the controller. If any of these dependencies are promises, 
31889            *   the router will wait for them all to be resolved before the controller is instantiated.
31890            *   If all the promises are resolved successfully, the $stateChangeSuccess event is fired
31891            *   and the values of the resolved promises are injected into any controllers that reference them.
31892            *   If any  of the promises are rejected the $stateChangeError event is fired.
31893            *
31894            *   The map object is:
31895            *   
31896            *   - key - {string}: name of dependency to be injected into controller
31897            *   - factory - {string|function}: If string then it is alias for service. Otherwise if function, 
31898            *     it is injected and return value it treated as dependency. If result is a promise, it is 
31899            *     resolved before its value is injected into controller.
31900            *
31901            * <pre>resolve: {
31902            *     myResolve1:
31903            *       function($http, $stateParams) {
31904            *         return $http.get("/api/foos/"+stateParams.fooID);
31905            *       }
31906            *     }</pre>
31907            *
31908            * @param {string=} stateConfig.url
31909            * <a id='url'></a>
31910            *
31911            *   A url fragment with optional parameters. When a state is navigated or
31912            *   transitioned to, the `$stateParams` service will be populated with any 
31913            *   parameters that were passed.
31914            *
31915            *   (See {@link ui.router.util.type:UrlMatcher UrlMatcher} `UrlMatcher`} for
31916            *   more details on acceptable patterns )
31917            *
31918            * examples:
31919            * <pre>url: "/home"
31920            * url: "/users/:userid"
31921            * url: "/books/{bookid:[a-zA-Z_-]}"
31922            * url: "/books/{categoryid:int}"
31923            * url: "/books/{publishername:string}/{categoryid:int}"
31924            * url: "/messages?before&after"
31925            * url: "/messages?{before:date}&{after:date}"
31926            * url: "/messages/:mailboxid?{before:date}&{after:date}"
31927            * </pre>
31928            *
31929            * @param {object=} stateConfig.views
31930            * <a id='views'></a>
31931            * an optional map&lt;string, object&gt; which defined multiple views, or targets views
31932            * manually/explicitly.
31933            *
31934            * Examples:
31935            *
31936            * Targets three named `ui-view`s in the parent state's template
31937            * <pre>views: {
31938            *     header: {
31939            *       controller: "headerCtrl",
31940            *       templateUrl: "header.html"
31941            *     }, body: {
31942            *       controller: "bodyCtrl",
31943            *       templateUrl: "body.html"
31944            *     }, footer: {
31945            *       controller: "footCtrl",
31946            *       templateUrl: "footer.html"
31947            *     }
31948            *   }</pre>
31949            *
31950            * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template.
31951            * <pre>views: {
31952            *     'header@top': {
31953            *       controller: "msgHeaderCtrl",
31954            *       templateUrl: "msgHeader.html"
31955            *     }, 'body': {
31956            *       controller: "messagesCtrl",
31957            *       templateUrl: "messages.html"
31958            *     }
31959            *   }</pre>
31960            *
31961            * @param {boolean=} [stateConfig.abstract=false]
31962            * <a id='abstract'></a>
31963            * An abstract state will never be directly activated,
31964            *   but can provide inherited properties to its common children states.
31965            * <pre>abstract: true</pre>
31966            *
31967            * @param {function=} stateConfig.onEnter
31968            * <a id='onEnter'></a>
31969            *
31970            * Callback function for when a state is entered. Good way
31971            *   to trigger an action or dispatch an event, such as opening a dialog.
31972 <<<<<<< HEAD
31973            * If minifying your scripts, make sure to explicitly annotate this function,
31974 =======
31975            * If minifying your scripts, make sure to explictly annotate this function,
31976 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31977            * because it won't be automatically annotated by your build tools.
31978            *
31979            * <pre>onEnter: function(MyService, $stateParams) {
31980            *     MyService.foo($stateParams.myParam);
31981            * }</pre>
31982            *
31983            * @param {function=} stateConfig.onExit
31984            * <a id='onExit'></a>
31985            *
31986            * Callback function for when a state is exited. Good way to
31987            *   trigger an action or dispatch an event, such as opening a dialog.
31988 <<<<<<< HEAD
31989            * If minifying your scripts, make sure to explicitly annotate this function,
31990 =======
31991            * If minifying your scripts, make sure to explictly annotate this function,
31992 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
31993            * because it won't be automatically annotated by your build tools.
31994            *
31995            * <pre>onExit: function(MyService, $stateParams) {
31996            *     MyService.cleanup($stateParams.myParam);
31997            * }</pre>
31998            *
31999            * @param {boolean=} [stateConfig.reloadOnSearch=true]
32000            * <a id='reloadOnSearch'></a>
32001            *
32002            * If `false`, will not retrigger the same state
32003            *   just because a search/query parameter has changed (via $location.search() or $location.hash()). 
32004            *   Useful for when you'd like to modify $location.search() without triggering a reload.
32005            * <pre>reloadOnSearch: false</pre>
32006            *
32007            * @param {object=} stateConfig.data
32008            * <a id='data'></a>
32009            *
32010            * Arbitrary data object, useful for custom configuration.  The parent state's `data` is
32011            *   prototypally inherited.  In other words, adding a data property to a state adds it to
32012            *   the entire subtree via prototypal inheritance.
32013            *
32014            * <pre>data: {
32015            *     requiredRole: 'foo'
32016            * } </pre>
32017            *
32018            * @param {object=} stateConfig.params
32019            * <a id='params'></a>
32020            *
32021            * A map which optionally configures parameters declared in the `url`, or
32022            *   defines additional non-url parameters.  For each parameter being
32023            *   configured, add a configuration object keyed to the name of the parameter.
32024            *
32025            *   Each parameter configuration object may contain the following properties:
32026            *
32027            *   - ** value ** - {object|function=}: specifies the default value for this
32028            *     parameter.  This implicitly sets this parameter as optional.
32029            *
32030            *     When UI-Router routes to a state and no value is
32031            *     specified for this parameter in the URL or transition, the
32032            *     default value will be used instead.  If `value` is a function,
32033            *     it will be injected and invoked, and the return value used.
32034            *
32035            *     *Note*: `undefined` is treated as "no default value" while `null`
32036            *     is treated as "the default value is `null`".
32037            *
32038            *     *Shorthand*: If you only need to configure the default value of the
32039            *     parameter, you may use a shorthand syntax.   In the **`params`**
32040            *     map, instead mapping the param name to a full parameter configuration
32041            *     object, simply set map it to the default parameter value, e.g.:
32042            *
32043            * <pre>// define a parameter's default value
32044            * params: {
32045            *     param1: { value: "defaultValue" }
32046            * }
32047            * // shorthand default values
32048            * params: {
32049            *     param1: "defaultValue",
32050            *     param2: "param2Default"
32051            * }</pre>
32052            *
32053            *   - ** array ** - {boolean=}: *(default: false)* If true, the param value will be
32054            *     treated as an array of values.  If you specified a Type, the value will be
32055            *     treated as an array of the specified Type.  Note: query parameter values
32056            *     default to a special `"auto"` mode.
32057            *
32058            *     For query parameters in `"auto"` mode, if multiple  values for a single parameter
32059            *     are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values
32060            *     are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`).  However, if
32061            *     only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single
32062            *     value (e.g.: `{ foo: '1' }`).
32063            *
32064            * <pre>params: {
32065            *     param1: { array: true }
32066            * }</pre>
32067            *
32068            *   - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when
32069            *     the current parameter value is the same as the default value. If `squash` is not set, it uses the
32070            *     configured default squash policy.
32071            *     (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`})
32072            *
32073            *   There are three squash settings:
32074            *
32075            *     - false: The parameter's default value is not squashed.  It is encoded and included in the URL
32076            *     - true: The parameter's default value is omitted from the URL.  If the parameter is preceeded and followed
32077            *       by slashes in the state's `url` declaration, then one of those slashes are omitted.
32078            *       This can allow for cleaner looking URLs.
32079            *     - `"<arbitrary string>"`: The parameter's default value is replaced with an arbitrary placeholder of  your choice.
32080            *
32081            * <pre>params: {
32082            *     param1: {
32083            *       value: "defaultId",
32084            *       squash: true
32085            * } }
32086            * // squash "defaultValue" to "~"
32087            * params: {
32088            *     param1: {
32089            *       value: "defaultValue",
32090            *       squash: "~"
32091            * } }
32092            * </pre>
32093            *
32094            *
32095            * @example
32096            * <pre>
32097            * // Some state name examples
32098            *
32099            * // stateName can be a single top-level name (must be unique).
32100            * $stateProvider.state("home", {});
32101            *
32102            * // Or it can be a nested state name. This state is a child of the
32103            * // above "home" state.
32104            * $stateProvider.state("home.newest", {});
32105            *
32106            * // Nest states as deeply as needed.
32107            * $stateProvider.state("home.newest.abc.xyz.inception", {});
32108            *
32109            * // state() returns $stateProvider, so you can chain state declarations.
32110            * $stateProvider
32111            *   .state("home", {})
32112            *   .state("about", {})
32113            *   .state("contacts", {});
32114            * </pre>
32115            *
32116            */
32117           this.state = state;
32118           function state(name, definition) {
32119             /*jshint validthis: true */
32120             if (isObject(name)) definition = name;
32121             else definition.name = name;
32122             registerState(definition);
32123             return this;
32124           }
32125
32126           /**
32127            * @ngdoc object
32128            * @name ui.router.state.$state
32129            *
32130            * @requires $rootScope
32131            * @requires $q
32132            * @requires ui.router.state.$view
32133            * @requires $injector
32134            * @requires ui.router.util.$resolve
32135            * @requires ui.router.state.$stateParams
32136            * @requires ui.router.router.$urlRouter
32137            *
32138            * @property {object} params A param object, e.g. {sectionId: section.id)}, that 
32139            * you'd like to test against the current active state.
32140            * @property {object} current A reference to the state's config object. However 
32141            * you passed it in. Useful for accessing custom data.
32142            * @property {object} transition Currently pending transition. A promise that'll 
32143            * resolve or reject.
32144            *
32145            * @description
32146            * `$state` service is responsible for representing states as well as transitioning
32147            * between them. It also provides interfaces to ask for current state or even states
32148            * you're coming from.
32149            */
32150           this.$get = $get;
32151           $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory'];
32152           function $get(   $rootScope,   $q,   $view,   $injector,   $resolve,   $stateParams,   $urlRouter,   $location,   $urlMatcherFactory) {
32153
32154             var TransitionSuperseded = $q.reject(new Error('transition superseded'));
32155             var TransitionPrevented = $q.reject(new Error('transition prevented'));
32156             var TransitionAborted = $q.reject(new Error('transition aborted'));
32157             var TransitionFailed = $q.reject(new Error('transition failed'));
32158
32159             // Handles the case where a state which is the target of a transition is not found, and the user
32160             // can optionally retry or defer the transition
32161             function handleRedirect(redirect, state, params, options) {
32162               /**
32163                * @ngdoc event
32164                * @name ui.router.state.$state#$stateNotFound
32165                * @eventOf ui.router.state.$state
32166                * @eventType broadcast on root scope
32167                * @description
32168                * Fired when a requested state **cannot be found** using the provided state name during transition.
32169                * The event is broadcast allowing any handlers a single chance to deal with the error (usually by
32170                * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler,
32171                * you can see its three properties in the example. You can use `event.preventDefault()` to abort the
32172                * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value.
32173                *
32174                * @param {Object} event Event object.
32175                * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties.
32176                * @param {State} fromState Current state object.
32177                * @param {Object} fromParams Current state params.
32178                *
32179                * @example
32180                *
32181                * <pre>
32182                * // somewhere, assume lazy.state has not been defined
32183                * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
32184                *
32185                * // somewhere else
32186                * $scope.$on('$stateNotFound',
32187                * function(event, unfoundState, fromState, fromParams){
32188                *     console.log(unfoundState.to); // "lazy.state"
32189                *     console.log(unfoundState.toParams); // {a:1, b:2}
32190                *     console.log(unfoundState.options); // {inherit:false} + default options
32191                * })
32192                * </pre>
32193                */
32194               var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params);
32195
32196               if (evt.defaultPrevented) {
32197                 $urlRouter.update();
32198                 return TransitionAborted;
32199               }
32200
32201               if (!evt.retry) {
32202                 return null;
32203               }
32204
32205               // Allow the handler to return a promise to defer state lookup retry
32206               if (options.$retry) {
32207                 $urlRouter.update();
32208                 return TransitionFailed;
32209               }
32210               var retryTransition = $state.transition = $q.when(evt.retry);
32211
32212               retryTransition.then(function() {
32213                 if (retryTransition !== $state.transition) return TransitionSuperseded;
32214                 redirect.options.$retry = true;
32215                 return $state.transitionTo(redirect.to, redirect.toParams, redirect.options);
32216               }, function() {
32217                 return TransitionAborted;
32218               });
32219               $urlRouter.update();
32220
32221               return retryTransition;
32222             }
32223
32224             root.locals = { resolve: null, globals: { $stateParams: {} } };
32225
32226             $state = {
32227               params: {},
32228               current: root.self,
32229               $current: root,
32230               transition: null
32231             };
32232
32233             /**
32234              * @ngdoc function
32235              * @name ui.router.state.$state#reload
32236              * @methodOf ui.router.state.$state
32237              *
32238              * @description
32239              * A method that force reloads the current state. All resolves are re-resolved,
32240              * controllers reinstantiated, and events re-fired.
32241              *
32242              * @example
32243              * <pre>
32244              * var app angular.module('app', ['ui.router']);
32245              *
32246              * app.controller('ctrl', function ($scope, $state) {
32247              *   $scope.reload = function(){
32248              *     $state.reload();
32249              *   }
32250              * });
32251              * </pre>
32252              *
32253              * `reload()` is just an alias for:
32254              * <pre>
32255              * $state.transitionTo($state.current, $stateParams, { 
32256              *   reload: true, inherit: false, notify: true
32257              * });
32258              * </pre>
32259              *
32260              * @param {string=|object=} state - A state name or a state object, which is the root of the resolves to be re-resolved.
32261              * @example
32262              * <pre>
32263              * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item' 
32264              * //and current state is 'contacts.detail.item'
32265              * var app angular.module('app', ['ui.router']);
32266              *
32267              * app.controller('ctrl', function ($scope, $state) {
32268              *   $scope.reload = function(){
32269              *     //will reload 'contact.detail' and 'contact.detail.item' states
32270              *     $state.reload('contact.detail');
32271              *   }
32272              * });
32273              * </pre>
32274              *
32275              * `reload()` is just an alias for:
32276              * <pre>
32277              * $state.transitionTo($state.current, $stateParams, { 
32278              *   reload: true, inherit: false, notify: true
32279              * });
32280              * </pre>
32281
32282              * @returns {promise} A promise representing the state of the new transition. See
32283              * {@link ui.router.state.$state#methods_go $state.go}.
32284              */
32285             $state.reload = function reload(state) {
32286               return $state.transitionTo($state.current, $stateParams, { reload: state || true, inherit: false, notify: true});
32287             };
32288
32289             /**
32290              * @ngdoc function
32291              * @name ui.router.state.$state#go
32292              * @methodOf ui.router.state.$state
32293              *
32294              * @description
32295              * Convenience method for transitioning to a new state. `$state.go` calls 
32296              * `$state.transitionTo` internally but automatically sets options to 
32297              * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. 
32298              * This allows you to easily use an absolute or relative to path and specify 
32299              * only the parameters you'd like to update (while letting unspecified parameters 
32300              * inherit from the currently active ancestor states).
32301              *
32302              * @example
32303              * <pre>
32304              * var app = angular.module('app', ['ui.router']);
32305              *
32306              * app.controller('ctrl', function ($scope, $state) {
32307              *   $scope.changeState = function () {
32308              *     $state.go('contact.detail');
32309              *   };
32310              * });
32311              * </pre>
32312              * <img src='../ngdoc_assets/StateGoExamples.png'/>
32313              *
32314              * @param {string} to Absolute state name or relative state path. Some examples:
32315              *
32316              * - `$state.go('contact.detail')` - will go to the `contact.detail` state
32317              * - `$state.go('^')` - will go to a parent state
32318              * - `$state.go('^.sibling')` - will go to a sibling state
32319              * - `$state.go('.child.grandchild')` - will go to grandchild state
32320              *
32321              * @param {object=} params A map of the parameters that will be sent to the state, 
32322              * will populate $stateParams. Any parameters that are not specified will be inherited from currently 
32323 <<<<<<< HEAD
32324              * defined parameters. Only parameters specified in the state definition can be overridden, new 
32325              * parameters will be ignored. This allows, for example, going to a sibling state that shares parameters
32326 =======
32327              * defined parameters. This allows, for example, going to a sibling state that shares parameters
32328 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
32329              * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e.
32330              * transitioning to a sibling will get you the parameters for all parents, transitioning to a child
32331              * will get you all current parameters, etc.
32332              * @param {object=} options Options object. The options are:
32333              *
32334              * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
32335              *    will not. If string, must be `"replace"`, which will update url and also replace last history record.
32336              * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
32337              * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), 
32338              *    defines which state to be relative from.
32339              * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
32340 <<<<<<< HEAD
32341              * - **`reload`** (v0.2.5) - {boolean=false|string|object}, If `true` will force transition even if no state or params
32342              *    have changed.  It will reload the resolves and views of the current state and parent states.
32343              *    If `reload` is a string (or state object), the state object is fetched (by name, or object reference); and \
32344              *    the transition reloads the resolves and views for that matched state, and all its children states.
32345 =======
32346              * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params 
32347              *    have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
32348              *    use this when you want to force a reload when *everything* is the same, including search params.
32349 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
32350              *
32351              * @returns {promise} A promise representing the state of the new transition.
32352              *
32353              * Possible success values:
32354              *
32355              * - $state.current
32356              *
32357              * <br/>Possible rejection values:
32358              *
32359              * - 'transition superseded' - when a newer transition has been started after this one
32360              * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener
32361              * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or
32362              *   when a `$stateNotFound` `event.retry` promise errors.
32363              * - 'transition failed' - when a state has been unsuccessfully found after 2 tries.
32364              * - *resolve error* - when an error has occurred with a `resolve`
32365              *
32366              */
32367             $state.go = function go(to, params, options) {
32368               return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options));
32369             };
32370
32371             /**
32372              * @ngdoc function
32373              * @name ui.router.state.$state#transitionTo
32374              * @methodOf ui.router.state.$state
32375              *
32376              * @description
32377              * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go}
32378              * uses `transitionTo` internally. `$state.go` is recommended in most situations.
32379              *
32380              * @example
32381              * <pre>
32382              * var app = angular.module('app', ['ui.router']);
32383              *
32384              * app.controller('ctrl', function ($scope, $state) {
32385              *   $scope.changeState = function () {
32386              *     $state.transitionTo('contact.detail');
32387              *   };
32388              * });
32389              * </pre>
32390              *
32391              * @param {string} to State name.
32392              * @param {object=} toParams A map of the parameters that will be sent to the state,
32393              * will populate $stateParams.
32394              * @param {object=} options Options object. The options are:
32395              *
32396              * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
32397              *    will not. If string, must be `"replace"`, which will update url and also replace last history record.
32398              * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url.
32399              * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), 
32400              *    defines which state to be relative from.
32401              * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
32402              * - **`reload`** (v0.2.5) - {boolean=false|string=|object=}, If `true` will force transition even if the state or params 
32403              *    have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
32404              *    use this when you want to force a reload when *everything* is the same, including search params.
32405              *    if String, then will reload the state with the name given in reload, and any children.
32406              *    if Object, then a stateObj is expected, will reload the state found in stateObj, and any children.
32407              *
32408              * @returns {promise} A promise representing the state of the new transition. See
32409              * {@link ui.router.state.$state#methods_go $state.go}.
32410              */
32411             $state.transitionTo = function transitionTo(to, toParams, options) {
32412               toParams = toParams || {};
32413               options = extend({
32414                 location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false
32415               }, options || {});
32416
32417               var from = $state.$current, fromParams = $state.params, fromPath = from.path;
32418               var evt, toState = findState(to, options.relative);
32419
32420               // Store the hash param for later (since it will be stripped out by various methods)
32421               var hash = toParams['#'];
32422
32423               if (!isDefined(toState)) {
32424                 var redirect = { to: to, toParams: toParams, options: options };
32425                 var redirectResult = handleRedirect(redirect, from.self, fromParams, options);
32426
32427                 if (redirectResult) {
32428                   return redirectResult;
32429                 }
32430
32431                 // Always retry once if the $stateNotFound was not prevented
32432                 // (handles either redirect changed or state lazy-definition)
32433                 to = redirect.to;
32434                 toParams = redirect.toParams;
32435                 options = redirect.options;
32436                 toState = findState(to, options.relative);
32437
32438                 if (!isDefined(toState)) {
32439                   if (!options.relative) throw new Error("No such state '" + to + "'");
32440                   throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'");
32441                 }
32442               }
32443               if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
32444               if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);
32445               if (!toState.params.$$validates(toParams)) return TransitionFailed;
32446
32447               toParams = toState.params.$$values(toParams);
32448               to = toState;
32449
32450               var toPath = to.path;
32451
32452               // Starting from the root of the path, keep all levels that haven't changed
32453               var keep = 0, state = toPath[keep], locals = root.locals, toLocals = [];
32454
32455               if (!options.reload) {
32456                 while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) {
32457                   locals = toLocals[keep] = state.locals;
32458                   keep++;
32459                   state = toPath[keep];
32460                 }
32461               } else if (isString(options.reload) || isObject(options.reload)) {
32462                 if (isObject(options.reload) && !options.reload.name) {
32463                   throw new Error('Invalid reload state object');
32464                 }
32465                 
32466                 var reloadState = options.reload === true ? fromPath[0] : findState(options.reload);
32467                 if (options.reload && !reloadState) {
32468                   throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'");
32469                 }
32470
32471                 while (state && state === fromPath[keep] && state !== reloadState) {
32472                   locals = toLocals[keep] = state.locals;
32473                   keep++;
32474                   state = toPath[keep];
32475                 }
32476               }
32477
32478               // If we're going to the same state and all locals are kept, we've got nothing to do.
32479               // But clear 'transition', as we still want to cancel any other pending transitions.
32480               // TODO: We may not want to bump 'transition' if we're called from a location change
32481               // that we've initiated ourselves, because we might accidentally abort a legitimate
32482               // transition initiated from code?
32483               if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) {
32484                 if (hash) toParams['#'] = hash;
32485                 $state.params = toParams;
32486                 copy($state.params, $stateParams);
32487 <<<<<<< HEAD
32488                 copy(filterByKeys(to.params.$$keys(), $stateParams), to.locals.globals.$stateParams);
32489 =======
32490 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
32491                 if (options.location && to.navigable && to.navigable.url) {
32492                   $urlRouter.push(to.navigable.url, toParams, {
32493                     $$avoidResync: true, replace: options.location === 'replace'
32494                   });
32495                   $urlRouter.update(true);
32496                 }
32497                 $state.transition = null;
32498                 return $q.when($state.current);
32499               }
32500
32501               // Filter parameters before we pass them to event handlers etc.
32502               toParams = filterByKeys(to.params.$$keys(), toParams || {});
32503 <<<<<<< HEAD
32504               
32505               // Re-add the saved hash before we start returning things or broadcasting $stateChangeStart
32506               if (hash) toParams['#'] = hash;
32507               
32508 =======
32509
32510 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
32511               // Broadcast start event and cancel the transition if requested
32512               if (options.notify) {
32513                 /**
32514                  * @ngdoc event
32515                  * @name ui.router.state.$state#$stateChangeStart
32516                  * @eventOf ui.router.state.$state
32517                  * @eventType broadcast on root scope
32518                  * @description
32519                  * Fired when the state transition **begins**. You can use `event.preventDefault()`
32520                  * to prevent the transition from happening and then the transition promise will be
32521                  * rejected with a `'transition prevented'` value.
32522                  *
32523                  * @param {Object} event Event object.
32524                  * @param {State} toState The state being transitioned to.
32525                  * @param {Object} toParams The params supplied to the `toState`.
32526                  * @param {State} fromState The current state, pre-transition.
32527                  * @param {Object} fromParams The params supplied to the `fromState`.
32528                  *
32529                  * @example
32530                  *
32531                  * <pre>
32532                  * $rootScope.$on('$stateChangeStart',
32533                  * function(event, toState, toParams, fromState, fromParams){
32534                  *     event.preventDefault();
32535                  *     // transitionTo() promise will be rejected with
32536                  *     // a 'transition prevented' error
32537                  * })
32538                  * </pre>
32539                  */
32540 <<<<<<< HEAD
32541                 if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams, options).defaultPrevented) {
32542                   $rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams);
32543                   //Don't update and resync url if there's been a new transition started. see issue #2238, #600
32544                   if ($state.transition == null) $urlRouter.update();
32545 =======
32546                 if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) {
32547                   $rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams);
32548                   $urlRouter.update();
32549 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
32550                   return TransitionPrevented;
32551                 }
32552               }
32553
32554               // Resolve locals for the remaining states, but don't update any global state just
32555               // yet -- if anything fails to resolve the current state needs to remain untouched.
32556               // We also set up an inheritance chain for the locals here. This allows the view directive
32557               // to quickly look up the correct definition for each view in the current state. Even
32558               // though we create the locals object itself outside resolveState(), it is initially
32559               // empty and gets filled asynchronously. We need to keep track of the promise for the
32560               // (fully resolved) current locals, and pass this down the chain.
32561               var resolved = $q.when(locals);
32562
32563               for (var l = keep; l < toPath.length; l++, state = toPath[l]) {
32564                 locals = toLocals[l] = inherit(locals);
32565                 resolved = resolveState(state, toParams, state === to, resolved, locals, options);
32566               }
32567
32568               // Once everything is resolved, we are ready to perform the actual transition
32569               // and return a promise for the new state. We also keep track of what the
32570               // current promise is, so that we can detect overlapping transitions and
32571               // keep only the outcome of the last transition.
32572               var transition = $state.transition = resolved.then(function () {
32573                 var l, entering, exiting;
32574
32575                 if ($state.transition !== transition) return TransitionSuperseded;
32576
32577                 // Exit 'from' states not kept
32578                 for (l = fromPath.length - 1; l >= keep; l--) {
32579                   exiting = fromPath[l];
32580                   if (exiting.self.onExit) {
32581                     $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals);
32582                   }
32583                   exiting.locals = null;
32584                 }
32585
32586                 // Enter 'to' states not kept
32587                 for (l = keep; l < toPath.length; l++) {
32588                   entering = toPath[l];
32589                   entering.locals = toLocals[l];
32590                   if (entering.self.onEnter) {
32591                     $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals);
32592                   }
32593                 }
32594
32595 <<<<<<< HEAD
32596 =======
32597                 // Re-add the saved hash before we start returning things
32598                 if (hash) toParams['#'] = hash;
32599
32600 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
32601                 // Run it again, to catch any transitions in callbacks
32602                 if ($state.transition !== transition) return TransitionSuperseded;
32603
32604                 // Update globals in $state
32605                 $state.$current = to;
32606                 $state.current = to.self;
32607                 $state.params = toParams;
32608                 copy($state.params, $stateParams);
32609                 $state.transition = null;
32610
32611                 if (options.location && to.navigable) {
32612                   $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, {
32613                     $$avoidResync: true, replace: options.location === 'replace'
32614                   });
32615                 }
32616
32617                 if (options.notify) {
32618                 /**
32619                  * @ngdoc event
32620                  * @name ui.router.state.$state#$stateChangeSuccess
32621                  * @eventOf ui.router.state.$state
32622                  * @eventType broadcast on root scope
32623                  * @description
32624                  * Fired once the state transition is **complete**.
32625                  *
32626                  * @param {Object} event Event object.
32627                  * @param {State} toState The state being transitioned to.
32628                  * @param {Object} toParams The params supplied to the `toState`.
32629                  * @param {State} fromState The current state, pre-transition.
32630                  * @param {Object} fromParams The params supplied to the `fromState`.
32631                  */
32632                   $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams);
32633                 }
32634                 $urlRouter.update(true);
32635
32636                 return $state.current;
32637               }, function (error) {
32638                 if ($state.transition !== transition) return TransitionSuperseded;
32639
32640                 $state.transition = null;
32641                 /**
32642                  * @ngdoc event
32643                  * @name ui.router.state.$state#$stateChangeError
32644                  * @eventOf ui.router.state.$state
32645                  * @eventType broadcast on root scope
32646                  * @description
32647                  * Fired when an **error occurs** during transition. It's important to note that if you
32648                  * have any errors in your resolve functions (javascript errors, non-existent services, etc)
32649                  * they will not throw traditionally. You must listen for this $stateChangeError event to
32650                  * catch **ALL** errors.
32651                  *
32652                  * @param {Object} event Event object.
32653                  * @param {State} toState The state being transitioned to.
32654                  * @param {Object} toParams The params supplied to the `toState`.
32655                  * @param {State} fromState The current state, pre-transition.
32656                  * @param {Object} fromParams The params supplied to the `fromState`.
32657                  * @param {Error} error The resolve error object.
32658                  */
32659                 evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error);
32660
32661                 if (!evt.defaultPrevented) {
32662                     $urlRouter.update();
32663                 }
32664
32665                 return $q.reject(error);
32666               });
32667
32668               return transition;
32669             };
32670
32671             /**
32672              * @ngdoc function
32673              * @name ui.router.state.$state#is
32674              * @methodOf ui.router.state.$state
32675              *
32676              * @description
32677              * Similar to {@link ui.router.state.$state#methods_includes $state.includes},
32678              * but only checks for the full state name. If params is supplied then it will be
32679              * tested for strict equality against the current active params object, so all params
32680              * must match with none missing and no extras.
32681              *
32682              * @example
32683              * <pre>
32684              * $state.$current.name = 'contacts.details.item';
32685              *
32686              * // absolute name
32687              * $state.is('contact.details.item'); // returns true
32688              * $state.is(contactDetailItemStateObject); // returns true
32689              *
32690              * // relative name (. and ^), typically from a template
32691              * // E.g. from the 'contacts.details' template
32692              * <div ng-class="{highlighted: $state.is('.item')}">Item</div>
32693              * </pre>
32694              *
32695              * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check.
32696              * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like
32697              * to test against the current active state.
32698              * @param {object=} options An options object.  The options are:
32699              *
32700              * - **`relative`** - {string|object} -  If `stateOrName` is a relative state name and `options.relative` is set, .is will
32701              * test relative to `options.relative` state (or name).
32702              *
32703              * @returns {boolean} Returns true if it is the state.
32704              */
32705             $state.is = function is(stateOrName, params, options) {
32706               options = extend({ relative: $state.$current }, options || {});
32707               var state = findState(stateOrName, options.relative);
32708
32709               if (!isDefined(state)) { return undefined; }
32710               if ($state.$current !== state) { return false; }
32711               return params ? equalForKeys(state.params.$$values(params), $stateParams) : true;
32712             };
32713
32714             /**
32715              * @ngdoc function
32716              * @name ui.router.state.$state#includes
32717              * @methodOf ui.router.state.$state
32718              *
32719              * @description
32720              * A method to determine if the current active state is equal to or is the child of the
32721              * state stateName. If any params are passed then they will be tested for a match as well.
32722              * Not all the parameters need to be passed, just the ones you'd like to test for equality.
32723              *
32724              * @example
32725              * Partial and relative names
32726              * <pre>
32727              * $state.$current.name = 'contacts.details.item';
32728              *
32729              * // Using partial names
32730              * $state.includes("contacts"); // returns true
32731              * $state.includes("contacts.details"); // returns true
32732              * $state.includes("contacts.details.item"); // returns true
32733              * $state.includes("contacts.list"); // returns false
32734              * $state.includes("about"); // returns false
32735              *
32736              * // Using relative names (. and ^), typically from a template
32737              * // E.g. from the 'contacts.details' template
32738              * <div ng-class="{highlighted: $state.includes('.item')}">Item</div>
32739              * </pre>
32740              *
32741              * Basic globbing patterns
32742              * <pre>
32743              * $state.$current.name = 'contacts.details.item.url';
32744              *
32745              * $state.includes("*.details.*.*"); // returns true
32746              * $state.includes("*.details.**"); // returns true
32747              * $state.includes("**.item.**"); // returns true
32748              * $state.includes("*.details.item.url"); // returns true
32749              * $state.includes("*.details.*.url"); // returns true
32750              * $state.includes("*.details.*"); // returns false
32751              * $state.includes("item.**"); // returns false
32752              * </pre>
32753              *
32754              * @param {string} stateOrName A partial name, relative name, or glob pattern
32755              * to be searched for within the current state name.
32756              * @param {object=} params A param object, e.g. `{sectionId: section.id}`,
32757              * that you'd like to test against the current active state.
32758              * @param {object=} options An options object.  The options are:
32759              *
32760              * - **`relative`** - {string|object=} -  If `stateOrName` is a relative state reference and `options.relative` is set,
32761              * .includes will test relative to `options.relative` state (or name).
32762              *
32763              * @returns {boolean} Returns true if it does include the state
32764              */
32765             $state.includes = function includes(stateOrName, params, options) {
32766               options = extend({ relative: $state.$current }, options || {});
32767               if (isString(stateOrName) && isGlob(stateOrName)) {
32768                 if (!doesStateMatchGlob(stateOrName)) {
32769                   return false;
32770                 }
32771                 stateOrName = $state.$current.name;
32772               }
32773
32774               var state = findState(stateOrName, options.relative);
32775               if (!isDefined(state)) { return undefined; }
32776               if (!isDefined($state.$current.includes[state.name])) { return false; }
32777               return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true;
32778             };
32779
32780
32781             /**
32782              * @ngdoc function
32783              * @name ui.router.state.$state#href
32784              * @methodOf ui.router.state.$state
32785              *
32786              * @description
32787              * A url generation method that returns the compiled url for the given state populated with the given params.
32788              *
32789              * @example
32790              * <pre>
32791              * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
32792              * </pre>
32793              *
32794              * @param {string|object} stateOrName The state name or state object you'd like to generate a url from.
32795              * @param {object=} params An object of parameter values to fill the state's required parameters.
32796              * @param {object=} options Options object. The options are:
32797              *
32798              * - **`lossy`** - {boolean=true} -  If true, and if there is no url associated with the state provided in the
32799              *    first parameter, then the constructed href url will be built from the first navigable ancestor (aka
32800              *    ancestor with a valid url).
32801              * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
32802              * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), 
32803              *    defines which state to be relative from.
32804              * - **`absolute`** - {boolean=false},  If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
32805              * 
32806              * @returns {string} compiled state url
32807              */
32808             $state.href = function href(stateOrName, params, options) {
32809               options = extend({
32810                 lossy:    true,
32811                 inherit:  true,
32812                 absolute: false,
32813                 relative: $state.$current
32814               }, options || {});
32815
32816               var state = findState(stateOrName, options.relative);
32817
32818               if (!isDefined(state)) return null;
32819               if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state);
32820               
32821               var nav = (state && options.lossy) ? state.navigable : state;
32822
32823               if (!nav || nav.url === undefined || nav.url === null) {
32824                 return null;
32825               }
32826               return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys().concat('#'), params || {}), {
32827                 absolute: options.absolute
32828               });
32829             };
32830
32831             /**
32832              * @ngdoc function
32833              * @name ui.router.state.$state#get
32834              * @methodOf ui.router.state.$state
32835              *
32836              * @description
32837              * Returns the state configuration object for any specific state or all states.
32838              *
32839              * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for
32840              * the requested state. If not provided, returns an array of ALL state configs.
32841              * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context.
32842              * @returns {Object|Array} State configuration object or array of all objects.
32843              */
32844             $state.get = function (stateOrName, context) {
32845               if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; });
32846               var state = findState(stateOrName, context || $state.$current);
32847               return (state && state.self) ? state.self : null;
32848             };
32849
32850             function resolveState(state, params, paramsAreFiltered, inherited, dst, options) {
32851               // Make a restricted $stateParams with only the parameters that apply to this state if
32852               // necessary. In addition to being available to the controller and onEnter/onExit callbacks,
32853               // we also need $stateParams to be available for any $injector calls we make during the
32854               // dependency resolution process.
32855               var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
32856               var locals = { $stateParams: $stateParams };
32857
32858               // Resolve 'global' dependencies for the state, i.e. those not specific to a view.
32859               // We're also including $stateParams in this; that way the parameters are restricted
32860               // to the set that should be visible to the state, and are independent of when we update
32861               // the global $state and $stateParams values.
32862               dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state);
32863               var promises = [dst.resolve.then(function (globals) {
32864                 dst.globals = globals;
32865               })];
32866               if (inherited) promises.push(inherited);
32867
32868               function resolveViews() {
32869                 var viewsPromises = [];
32870
32871                 // Resolve template and dependencies for all views.
32872                 forEach(state.views, function (view, name) {
32873                   var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {});
32874                   injectables.$template = [ function () {
32875                     return $view.load(name, { view: view, locals: dst.globals, params: $stateParams, notify: options.notify }) || '';
32876                   }];
32877
32878                   viewsPromises.push($resolve.resolve(injectables, dst.globals, dst.resolve, state).then(function (result) {
32879                     // References to the controller (only instantiated at link time)
32880                     if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) {
32881                       var injectLocals = angular.extend({}, injectables, dst.globals);
32882                       result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals);
32883                     } else {
32884                       result.$$controller = view.controller;
32885                     }
32886                     // Provide access to the state itself for internal use
32887                     result.$$state = state;
32888                     result.$$controllerAs = view.controllerAs;
32889                     dst[name] = result;
32890                   }));
32891                 });
32892
32893                 return $q.all(viewsPromises).then(function(){
32894                   return dst.globals;
32895                 });
32896               }
32897
32898               // Wait for all the promises and then return the activation object
32899               return $q.all(promises).then(resolveViews).then(function (values) {
32900                 return dst;
32901               });
32902             }
32903
32904             return $state;
32905           }
32906
32907           function shouldSkipReload(to, toParams, from, fromParams, locals, options) {
32908             // Return true if there are no differences in non-search (path/object) params, false if there are differences
32909             function nonSearchParamsEqual(fromAndToState, fromParams, toParams) {
32910               // Identify whether all the parameters that differ between `fromParams` and `toParams` were search params.
32911               function notSearchParam(key) {
32912                 return fromAndToState.params[key].location != "search";
32913               }
32914               var nonQueryParamKeys = fromAndToState.params.$$keys().filter(notSearchParam);
32915               var nonQueryParams = pick.apply({}, [fromAndToState.params].concat(nonQueryParamKeys));
32916               var nonQueryParamSet = new $$UMFP.ParamSet(nonQueryParams);
32917               return nonQueryParamSet.$$equals(fromParams, toParams);
32918             }
32919
32920             // If reload was not explicitly requested
32921             // and we're transitioning to the same state we're already in
32922             // and    the locals didn't change
32923             //     or they changed in a way that doesn't merit reloading
32924             //        (reloadOnParams:false, or reloadOnSearch.false and only search params changed)
32925             // Then return true.
32926             if (!options.reload && to === from &&
32927               (locals === from.locals || (to.self.reloadOnSearch === false && nonSearchParamsEqual(from, fromParams, toParams)))) {
32928               return true;
32929             }
32930           }
32931         }
32932
32933         angular.module('ui.router.state')
32934 <<<<<<< HEAD
32935           .factory('$stateParams', function () { return {}; })
32936 =======
32937           .value('$stateParams', {})
32938 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
32939           .provider('$state', $StateProvider);
32940
32941
32942         $ViewProvider.$inject = [];
32943         function $ViewProvider() {
32944
32945           this.$get = $get;
32946           /**
32947            * @ngdoc object
32948            * @name ui.router.state.$view
32949            *
32950            * @requires ui.router.util.$templateFactory
32951            * @requires $rootScope
32952            *
32953            * @description
32954            *
32955            */
32956           $get.$inject = ['$rootScope', '$templateFactory'];
32957           function $get(   $rootScope,   $templateFactory) {
32958             return {
32959               // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... })
32960               /**
32961                * @ngdoc function
32962                * @name ui.router.state.$view#load
32963                * @methodOf ui.router.state.$view
32964                *
32965                * @description
32966                *
32967                * @param {string} name name
32968                * @param {object} options option object.
32969                */
32970               load: function load(name, options) {
32971                 var result, defaults = {
32972                   template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {}
32973                 };
32974                 options = extend(defaults, options);
32975
32976                 if (options.view) {
32977                   result = $templateFactory.fromConfig(options.view, options.params, options.locals);
32978                 }
32979 <<<<<<< HEAD
32980 =======
32981                 if (result && options.notify) {
32982                 /**
32983                  * @ngdoc event
32984                  * @name ui.router.state.$state#$viewContentLoading
32985                  * @eventOf ui.router.state.$view
32986                  * @eventType broadcast on root scope
32987                  * @description
32988                  *
32989                  * Fired once the view **begins loading**, *before* the DOM is rendered.
32990                  *
32991                  * @param {Object} event Event object.
32992                  * @param {Object} viewConfig The view config properties (template, controller, etc).
32993                  *
32994                  * @example
32995                  *
32996                  * <pre>
32997                  * $scope.$on('$viewContentLoading',
32998                  * function(event, viewConfig){
32999                  *     // Access to all the view config properties.
33000                  *     // and one special property 'targetView'
33001                  *     // viewConfig.targetView
33002                  * });
33003                  * </pre>
33004                  */
33005                   $rootScope.$broadcast('$viewContentLoading', options);
33006                 }
33007 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33008                 return result;
33009               }
33010             };
33011           }
33012         }
33013
33014         angular.module('ui.router.state').provider('$view', $ViewProvider);
33015
33016         /**
33017          * @ngdoc object
33018          * @name ui.router.state.$uiViewScrollProvider
33019          *
33020          * @description
33021          * Provider that returns the {@link ui.router.state.$uiViewScroll} service function.
33022          */
33023         function $ViewScrollProvider() {
33024
33025           var useAnchorScroll = false;
33026
33027           /**
33028            * @ngdoc function
33029            * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll
33030            * @methodOf ui.router.state.$uiViewScrollProvider
33031            *
33032            * @description
33033            * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for
33034            * scrolling based on the url anchor.
33035            */
33036           this.useAnchorScroll = function () {
33037             useAnchorScroll = true;
33038           };
33039
33040           /**
33041            * @ngdoc object
33042            * @name ui.router.state.$uiViewScroll
33043            *
33044            * @requires $anchorScroll
33045            * @requires $timeout
33046            *
33047            * @description
33048            * When called with a jqLite element, it scrolls the element into view (after a
33049            * `$timeout` so the DOM has time to refresh).
33050            *
33051            * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor,
33052            * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}.
33053            */
33054           this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) {
33055             if (useAnchorScroll) {
33056               return $anchorScroll;
33057             }
33058
33059             return function ($element) {
33060               return $timeout(function () {
33061                 $element[0].scrollIntoView();
33062               }, 0, false);
33063             };
33064           }];
33065         }
33066
33067         angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider);
33068
33069 <<<<<<< HEAD
33070         var ngMajorVer = angular.version.major;
33071         var ngMinorVer = angular.version.minor;
33072 =======
33073 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33074         /**
33075          * @ngdoc directive
33076          * @name ui.router.state.directive:ui-view
33077          *
33078          * @requires ui.router.state.$state
33079          * @requires $compile
33080          * @requires $controller
33081          * @requires $injector
33082          * @requires ui.router.state.$uiViewScroll
33083          * @requires $document
33084          *
33085          * @restrict ECA
33086          *
33087          * @description
33088          * The ui-view directive tells $state where to place your templates.
33089          *
33090          * @param {string=} name A view name. The name should be unique amongst the other views in the
33091          * same state. You can have views of the same name that live in different states.
33092          *
33093          * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window
33094          * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll
33095          * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you
33096          * scroll ui-view elements into view when they are populated during a state activation.
33097          *
33098 <<<<<<< HEAD
33099          * @param {string=} noanimation If truthy, the non-animated renderer will be selected (no animations
33100          * will be applied to the ui-view)
33101          *
33102 =======
33103 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33104          * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)
33105          * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*
33106          *
33107          * @param {string=} onload Expression to evaluate whenever the view updates.
33108          * 
33109          * @example
33110          * A view can be unnamed or named. 
33111          * <pre>
33112          * <!-- Unnamed -->
33113          * <div ui-view></div> 
33114          * 
33115          * <!-- Named -->
33116          * <div ui-view="viewName"></div>
33117          * </pre>
33118          *
33119          * You can only have one unnamed view within any template (or root html). If you are only using a 
33120          * single view and it is unnamed then you can populate it like so:
33121          * <pre>
33122          * <div ui-view></div> 
33123          * $stateProvider.state("home", {
33124          *   template: "<h1>HELLO!</h1>"
33125          * })
33126          * </pre>
33127          * 
33128          * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`}
33129          * config property, by name, in this case an empty name:
33130          * <pre>
33131          * $stateProvider.state("home", {
33132          *   views: {
33133          *     "": {
33134          *       template: "<h1>HELLO!</h1>"
33135          *     }
33136          *   }    
33137          * })
33138          * </pre>
33139          * 
33140          * But typically you'll only use the views property if you name your view or have more than one view 
33141          * in the same template. There's not really a compelling reason to name a view if its the only one, 
33142          * but you could if you wanted, like so:
33143          * <pre>
33144          * <div ui-view="main"></div>
33145          * </pre> 
33146          * <pre>
33147          * $stateProvider.state("home", {
33148          *   views: {
33149          *     "main": {
33150          *       template: "<h1>HELLO!</h1>"
33151          *     }
33152          *   }    
33153          * })
33154          * </pre>
33155          * 
33156          * Really though, you'll use views to set up multiple views:
33157          * <pre>
33158          * <div ui-view></div>
33159          * <div ui-view="chart"></div> 
33160          * <div ui-view="data"></div> 
33161          * </pre>
33162          * 
33163          * <pre>
33164          * $stateProvider.state("home", {
33165          *   views: {
33166          *     "": {
33167          *       template: "<h1>HELLO!</h1>"
33168          *     },
33169          *     "chart": {
33170          *       template: "<chart_thing/>"
33171          *     },
33172          *     "data": {
33173          *       template: "<data_thing/>"
33174          *     }
33175          *   }    
33176          * })
33177          * </pre>
33178          *
33179          * Examples for `autoscroll`:
33180          *
33181          * <pre>
33182          * <!-- If autoscroll present with no expression,
33183          *      then scroll ui-view into view -->
33184          * <ui-view autoscroll/>
33185          *
33186          * <!-- If autoscroll present with valid expression,
33187          *      then scroll ui-view into view if expression evaluates to true -->
33188          * <ui-view autoscroll='true'/>
33189          * <ui-view autoscroll='false'/>
33190          * <ui-view autoscroll='scopeVariable'/>
33191          * </pre>
33192          */
33193         $ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate'];
33194         function $ViewDirective(   $state,   $injector,   $uiViewScroll,   $interpolate) {
33195
33196           function getService() {
33197             return ($injector.has) ? function(service) {
33198               return $injector.has(service) ? $injector.get(service) : null;
33199             } : function(service) {
33200               try {
33201                 return $injector.get(service);
33202               } catch (e) {
33203                 return null;
33204               }
33205             };
33206           }
33207
33208           var service = getService(),
33209               $animator = service('$animator'),
33210               $animate = service('$animate');
33211
33212           // Returns a set of DOM manipulation functions based on which Angular version
33213           // it should use
33214           function getRenderer(attrs, scope) {
33215 <<<<<<< HEAD
33216             var statics = {
33217               enter: function (element, target, cb) { target.after(element); cb(); },
33218               leave: function (element, cb) { element.remove(); cb(); }
33219             };
33220
33221             if (!!attrs.noanimation) return statics;
33222
33223             function animEnabled(element) {
33224               if (ngMajorVer === 1 && ngMinorVer >= 4) return !!$animate.enabled(element);
33225               if (ngMajorVer === 1 && ngMinorVer >= 2) return !!$animate.enabled();
33226               return (!!$animator);
33227             }
33228
33229             // ng 1.2+
33230             if ($animate) {
33231               return {
33232                 enter: function(element, target, cb) {
33233                   if (!animEnabled(element)) {
33234                     statics.enter(element, target, cb);
33235                   } else if (angular.version.minor > 2) {
33236                     $animate.enter(element, null, target).then(cb);
33237                   } else {
33238                     $animate.enter(element, null, target, cb);
33239                   }
33240                 },
33241                 leave: function(element, cb) {
33242                   if (!animEnabled(element)) {
33243                     statics.leave(element, cb);
33244                   } else if (angular.version.minor > 2) {
33245                     $animate.leave(element).then(cb);
33246                   } else {
33247                     $animate.leave(element, cb);
33248                   }
33249 =======
33250             var statics = function() {
33251               return {
33252                 enter: function (element, target, cb) { target.after(element); cb(); },
33253                 leave: function (element, cb) { element.remove(); cb(); }
33254               };
33255             };
33256
33257             if ($animate) {
33258               return {
33259                 enter: function(element, target, cb) {
33260                   var promise = $animate.enter(element, null, target, cb);
33261                   if (promise && promise.then) promise.then(cb);
33262                 },
33263                 leave: function(element, cb) {
33264                   var promise = $animate.leave(element, cb);
33265                   if (promise && promise.then) promise.then(cb);
33266 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33267                 }
33268               };
33269             }
33270
33271 <<<<<<< HEAD
33272             // ng 1.1.5
33273 =======
33274 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33275             if ($animator) {
33276               var animate = $animator && $animator(scope, attrs);
33277
33278               return {
33279                 enter: function(element, target, cb) {animate.enter(element, null, target); cb(); },
33280                 leave: function(element, cb) { animate.leave(element); cb(); }
33281               };
33282             }
33283
33284 <<<<<<< HEAD
33285             return statics;
33286 =======
33287             return statics();
33288 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33289           }
33290
33291           var directive = {
33292             restrict: 'ECA',
33293             terminal: true,
33294             priority: 400,
33295             transclude: 'element',
33296             compile: function (tElement, tAttrs, $transclude) {
33297               return function (scope, $element, attrs) {
33298                 var previousEl, currentEl, currentScope, latestLocals,
33299                     onloadExp     = attrs.onload || '',
33300                     autoScrollExp = attrs.autoscroll,
33301                     renderer      = getRenderer(attrs, scope);
33302
33303                 scope.$on('$stateChangeSuccess', function() {
33304                   updateView(false);
33305                 });
33306 <<<<<<< HEAD
33307 =======
33308                 scope.$on('$viewContentLoading', function() {
33309                   updateView(false);
33310                 });
33311 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33312
33313                 updateView(true);
33314
33315                 function cleanupLastView() {
33316 <<<<<<< HEAD
33317                   var _previousEl = previousEl;
33318                   var _currentScope = currentScope;
33319
33320                   if (_currentScope) {
33321                     _currentScope._willBeDestroyed = true;
33322                   }
33323
33324                   function cleanOld() {
33325                     if (_previousEl) {
33326                       _previousEl.remove();
33327                     }
33328
33329                     if (_currentScope) {
33330                       _currentScope.$destroy();
33331                     }
33332 =======
33333                   if (previousEl) {
33334                     previousEl.remove();
33335                     previousEl = null;
33336                   }
33337
33338                   if (currentScope) {
33339                     currentScope.$destroy();
33340                     currentScope = null;
33341 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33342                   }
33343
33344                   if (currentEl) {
33345                     renderer.leave(currentEl, function() {
33346 <<<<<<< HEAD
33347                       cleanOld();
33348 =======
33349 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33350                       previousEl = null;
33351                     });
33352
33353                     previousEl = currentEl;
33354 <<<<<<< HEAD
33355                   } else {
33356                     cleanOld();
33357                     previousEl = null;
33358                   }
33359
33360                   currentEl = null;
33361                   currentScope = null;
33362 =======
33363                     currentEl = null;
33364                   }
33365 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33366                 }
33367
33368                 function updateView(firstTime) {
33369                   var newScope,
33370                       name            = getUiViewName(scope, attrs, $element, $interpolate),
33371                       previousLocals  = name && $state.$current && $state.$current.locals[name];
33372
33373 <<<<<<< HEAD
33374                   if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do
33375                   newScope = scope.$new();
33376                   latestLocals = $state.$current.locals[name];
33377
33378                   /**
33379                    * @ngdoc event
33380                    * @name ui.router.state.directive:ui-view#$viewContentLoading
33381                    * @eventOf ui.router.state.directive:ui-view
33382                    * @eventType emits on ui-view directive scope
33383                    * @description
33384                    *
33385                    * Fired once the view **begins loading**, *before* the DOM is rendered.
33386                    *
33387                    * @param {Object} event Event object.
33388                    * @param {string} viewName Name of the view.
33389                    */
33390                   newScope.$emit('$viewContentLoading', name);
33391
33392 =======
33393                   if (!firstTime && previousLocals === latestLocals) return; // nothing to do
33394                   newScope = scope.$new();
33395                   latestLocals = $state.$current.locals[name];
33396
33397 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33398                   var clone = $transclude(newScope, function(clone) {
33399                     renderer.enter(clone, $element, function onUiViewEnter() {
33400                       if(currentScope) {
33401                         currentScope.$emit('$viewContentAnimationEnded');
33402                       }
33403
33404                       if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) {
33405                         $uiViewScroll(clone);
33406                       }
33407                     });
33408                     cleanupLastView();
33409                   });
33410
33411                   currentEl = clone;
33412                   currentScope = newScope;
33413                   /**
33414                    * @ngdoc event
33415                    * @name ui.router.state.directive:ui-view#$viewContentLoaded
33416                    * @eventOf ui.router.state.directive:ui-view
33417                    * @eventType emits on ui-view directive scope
33418 <<<<<<< HEAD
33419                    * @description
33420                    * Fired once the view is **loaded**, *after* the DOM is rendered.
33421                    *
33422                    * @param {Object} event Event object.
33423                    * @param {string} viewName Name of the view.
33424                    */
33425                   currentScope.$emit('$viewContentLoaded', name);
33426 =======
33427                    * @description           *
33428                    * Fired once the view is **loaded**, *after* the DOM is rendered.
33429                    *
33430                    * @param {Object} event Event object.
33431                    */
33432                   currentScope.$emit('$viewContentLoaded');
33433 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33434                   currentScope.$eval(onloadExp);
33435                 }
33436               };
33437             }
33438           };
33439
33440           return directive;
33441         }
33442
33443         $ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate'];
33444         function $ViewDirectiveFill (  $compile,   $controller,   $state,   $interpolate) {
33445           return {
33446             restrict: 'ECA',
33447             priority: -400,
33448             compile: function (tElement) {
33449               var initial = tElement.html();
33450               return function (scope, $element, attrs) {
33451                 var current = $state.$current,
33452                     name = getUiViewName(scope, attrs, $element, $interpolate),
33453                     locals  = current && current.locals[name];
33454
33455                 if (! locals) {
33456                   return;
33457                 }
33458
33459                 $element.data('$uiView', { name: name, state: locals.$$state });
33460                 $element.html(locals.$template ? locals.$template : initial);
33461
33462                 var link = $compile($element.contents());
33463
33464                 if (locals.$$controller) {
33465                   locals.$scope = scope;
33466                   locals.$element = $element;
33467                   var controller = $controller(locals.$$controller, locals);
33468                   if (locals.$$controllerAs) {
33469                     scope[locals.$$controllerAs] = controller;
33470                   }
33471                   $element.data('$ngControllerController', controller);
33472                   $element.children().data('$ngControllerController', controller);
33473                 }
33474
33475                 link(scope);
33476               };
33477             }
33478           };
33479         }
33480
33481         /**
33482          * Shared ui-view code for both directives:
33483          * Given scope, element, and its attributes, return the view's name
33484          */
33485         function getUiViewName(scope, attrs, element, $interpolate) {
33486           var name = $interpolate(attrs.uiView || attrs.name || '')(scope);
33487           var inherited = element.inheritedData('$uiView');
33488           return name.indexOf('@') >= 0 ?  name :  (name + '@' + (inherited ? inherited.state.name : ''));
33489         }
33490
33491         angular.module('ui.router.state').directive('uiView', $ViewDirective);
33492         angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill);
33493
33494         function parseStateRef(ref, current) {
33495           var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed;
33496           if (preparsed) ref = current + '(' + preparsed[1] + ')';
33497           parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
33498           if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'");
33499           return { state: parsed[1], paramExpr: parsed[3] || null };
33500         }
33501
33502         function stateContext(el) {
33503           var stateData = el.parent().inheritedData('$uiView');
33504
33505           if (stateData && stateData.state && stateData.state.name) {
33506             return stateData.state;
33507           }
33508         }
33509
33510 <<<<<<< HEAD
33511         function getTypeInfo(el) {
33512           // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
33513           var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]';
33514           var isForm = el[0].nodeName === "FORM";
33515
33516           return {
33517             attr: isForm ? "action" : (isSvg ? 'xlink:href' : 'href'),
33518             isAnchor: el.prop("tagName").toUpperCase() === "A",
33519             clickable: !isForm
33520           };
33521         }
33522
33523         function clickHook(el, $state, $timeout, type, current) {
33524           return function(e) {
33525             var button = e.which || e.button, target = current();
33526
33527             if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) {
33528               // HACK: This is to allow ng-clicks to be processed before the transition is initiated:
33529               var transition = $timeout(function() {
33530                 $state.go(target.state, target.params, target.options);
33531               });
33532               e.preventDefault();
33533
33534               // if the state has no URL, ignore one preventDefault from the <a> directive.
33535               var ignorePreventDefaultCount = type.isAnchor && !target.href ? 1: 0;
33536
33537               e.preventDefault = function() {
33538                 if (ignorePreventDefaultCount-- <= 0) $timeout.cancel(transition);
33539               };
33540             }
33541           };
33542         }
33543
33544         function defaultOpts(el, $state) {
33545           return { relative: stateContext(el) || $state.$current, inherit: true };
33546         }
33547
33548 =======
33549 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33550         /**
33551          * @ngdoc directive
33552          * @name ui.router.state.directive:ui-sref
33553          *
33554          * @requires ui.router.state.$state
33555          * @requires $timeout
33556          *
33557          * @restrict A
33558          *
33559          * @description
33560 <<<<<<< HEAD
33561          * A directive that binds a link (`<a>` tag) to a state. If the state has an associated
33562          * URL, the directive will automatically generate & update the `href` attribute via
33563          * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking
33564          * the link will trigger a state transition with optional parameters.
33565          *
33566          * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be
33567          * handled natively by the browser.
33568          *
33569          * You can also use relative state paths within ui-sref, just like the relative
33570          * paths passed to `$state.go()`. You just need to be aware that the path is relative
33571          * to the state that the link lives in, in other words the state that loaded the
33572 =======
33573          * A directive that binds a link (`<a>` tag) to a state. If the state has an associated 
33574          * URL, the directive will automatically generate & update the `href` attribute via 
33575          * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking 
33576          * the link will trigger a state transition with optional parameters. 
33577          *
33578          * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be 
33579          * handled natively by the browser.
33580          *
33581          * You can also use relative state paths within ui-sref, just like the relative 
33582          * paths passed to `$state.go()`. You just need to be aware that the path is relative
33583          * to the state that the link lives in, in other words the state that loaded the 
33584 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33585          * template containing the link.
33586          *
33587          * You can specify options to pass to {@link ui.router.state.$state#go $state.go()}
33588          * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`,
33589          * and `reload`.
33590          *
33591          * @example
33592 <<<<<<< HEAD
33593          * Here's an example of how you'd use ui-sref and how it would compile. If you have the
33594          * following template:
33595          * <pre>
33596          * <a ui-sref="home">Home</a> | <a ui-sref="about">About</a> | <a ui-sref="{page: 2}">Next page</a>
33597          *
33598 =======
33599          * Here's an example of how you'd use ui-sref and how it would compile. If you have the 
33600          * following template:
33601          * <pre>
33602          * <a ui-sref="home">Home</a> | <a ui-sref="about">About</a> | <a ui-sref="{page: 2}">Next page</a>
33603          * 
33604 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33605          * <ul>
33606          *     <li ng-repeat="contact in contacts">
33607          *         <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
33608          *     </li>
33609          * </ul>
33610          * </pre>
33611 <<<<<<< HEAD
33612          *
33613          * Then the compiled html would be (assuming Html5Mode is off and current state is contacts):
33614          * <pre>
33615          * <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a> | <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
33616          *
33617 =======
33618          * 
33619          * Then the compiled html would be (assuming Html5Mode is off and current state is contacts):
33620          * <pre>
33621          * <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a> | <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
33622          * 
33623 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33624          * <ul>
33625          *     <li ng-repeat="contact in contacts">
33626          *         <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
33627          *     </li>
33628          *     <li ng-repeat="contact in contacts">
33629          *         <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
33630          *     </li>
33631          *     <li ng-repeat="contact in contacts">
33632          *         <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
33633          *     </li>
33634          * </ul>
33635          *
33636          * <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
33637          * </pre>
33638          *
33639          * @param {string} ui-sref 'stateName' can be any valid absolute or relative state
33640          * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()}
33641          */
33642         $StateRefDirective.$inject = ['$state', '$timeout'];
33643         function $StateRefDirective($state, $timeout) {
33644 <<<<<<< HEAD
33645 =======
33646           var allowedOptions = ['location', 'inherit', 'reload', 'absolute'];
33647
33648 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33649           return {
33650             restrict: 'A',
33651             require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
33652             link: function(scope, element, attrs, uiSrefActive) {
33653 <<<<<<< HEAD
33654               var ref    = parseStateRef(attrs.uiSref, $state.current.name);
33655               var def    = { state: ref.state, href: null, params: null };
33656               var type   = getTypeInfo(element);
33657               var active = uiSrefActive[1] || uiSrefActive[0];
33658
33659               def.options = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {});
33660
33661               var update = function(val) {
33662                 if (val) def.params = angular.copy(val);
33663                 def.href = $state.href(ref.state, def.params, def.options);
33664
33665                 if (active) active.$$addStateInfo(ref.state, def.params);
33666                 if (def.href !== null) attrs.$set(type.attr, def.href);
33667               };
33668
33669               if (ref.paramExpr) {
33670                 scope.$watch(ref.paramExpr, function(val) { if (val !== def.params) update(val); }, true);
33671                 def.params = angular.copy(scope.$eval(ref.paramExpr));
33672               }
33673               update();
33674
33675               if (!type.clickable) return;
33676               element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; }));
33677             }
33678           };
33679         }
33680
33681         /**
33682          * @ngdoc directive
33683          * @name ui.router.state.directive:ui-state
33684          *
33685          * @requires ui.router.state.uiSref
33686          *
33687          * @restrict A
33688          *
33689          * @description
33690          * Much like ui-sref, but will accept named $scope properties to evaluate for a state definition,
33691          * params and override options.
33692          *
33693          * @param {string} ui-state 'stateName' can be any valid absolute or relative state
33694          * @param {Object} ui-state-params params to pass to {@link ui.router.state.$state#href $state.href()}
33695          * @param {Object} ui-state-opts options to pass to {@link ui.router.state.$state#go $state.go()}
33696          */
33697         $StateRefDynamicDirective.$inject = ['$state', '$timeout'];
33698         function $StateRefDynamicDirective($state, $timeout) {
33699           return {
33700             restrict: 'A',
33701             require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
33702             link: function(scope, element, attrs, uiSrefActive) {
33703               var type   = getTypeInfo(element);
33704               var active = uiSrefActive[1] || uiSrefActive[0];
33705               var group  = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null];
33706               var watch  = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']';
33707               var def    = { state: null, params: null, options: null, href: null };
33708
33709               function runStateRefLink (group) {
33710                 def.state = group[0]; def.params = group[1]; def.options = group[2];
33711                 def.href = $state.href(def.state, def.params, def.options);
33712
33713                 if (active) active.$$addStateInfo(def.state, def.params);
33714                 if (def.href) attrs.$set(type.attr, def.href);
33715               }
33716
33717               scope.$watch(watch, runStateRefLink, true);
33718               runStateRefLink(scope.$eval(watch));
33719
33720               if (!type.clickable) return;
33721               element.bind("click", clickHook(element, $state, $timeout, type, function() { return def; }));
33722 =======
33723               var ref = parseStateRef(attrs.uiSref, $state.current.name);
33724               var params = null, url = null, base = stateContext(element) || $state.$current;
33725               // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
33726               var hrefKind = Object.prototype.toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
33727                          'xlink:href' : 'href';
33728               var newHref = null, isAnchor = element.prop("tagName").toUpperCase() === "A";
33729               var isForm = element[0].nodeName === "FORM";
33730               var attr = isForm ? "action" : hrefKind, nav = true;
33731
33732               var options = { relative: base, inherit: true };
33733               var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {};
33734
33735               angular.forEach(allowedOptions, function(option) {
33736                 if (option in optionsOverride) {
33737                   options[option] = optionsOverride[option];
33738                 }
33739               });
33740
33741               var update = function(newVal) {
33742                 if (newVal) params = angular.copy(newVal);
33743                 if (!nav) return;
33744
33745                 newHref = $state.href(ref.state, params, options);
33746
33747                 var activeDirective = uiSrefActive[1] || uiSrefActive[0];
33748                 if (activeDirective) {
33749                   activeDirective.$$addStateInfo(ref.state, params);
33750                 }
33751                 if (newHref === null) {
33752                   nav = false;
33753                   return false;
33754                 }
33755                 attrs.$set(attr, newHref);
33756               };
33757
33758               if (ref.paramExpr) {
33759                 scope.$watch(ref.paramExpr, function(newVal, oldVal) {
33760                   if (newVal !== params) update(newVal);
33761                 }, true);
33762                 params = angular.copy(scope.$eval(ref.paramExpr));
33763               }
33764               update();
33765
33766               if (isForm) return;
33767
33768               element.bind("click", function(e) {
33769                 var button = e.which || e.button;
33770                 if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) {
33771                   // HACK: This is to allow ng-clicks to be processed before the transition is initiated:
33772                   var transition = $timeout(function() {
33773                     $state.go(ref.state, params, options);
33774                   });
33775                   e.preventDefault();
33776
33777                   // if the state has no URL, ignore one preventDefault from the <a> directive.
33778                   var ignorePreventDefaultCount = isAnchor && !newHref ? 1: 0;
33779                   e.preventDefault = function() {
33780                     if (ignorePreventDefaultCount-- <= 0)
33781                       $timeout.cancel(transition);
33782                   };
33783                 }
33784               });
33785 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33786             }
33787           };
33788         }
33789
33790 <<<<<<< HEAD
33791
33792 =======
33793 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33794         /**
33795          * @ngdoc directive
33796          * @name ui.router.state.directive:ui-sref-active
33797          *
33798          * @requires ui.router.state.$state
33799          * @requires ui.router.state.$stateParams
33800          * @requires $interpolate
33801          *
33802          * @restrict A
33803          *
33804          * @description
33805          * A directive working alongside ui-sref to add classes to an element when the
33806          * related ui-sref directive's state is active, and removing them when it is inactive.
33807          * The primary use-case is to simplify the special appearance of navigation menus
33808          * relying on `ui-sref`, by having the "active" state's menu button appear different,
33809          * distinguishing it from the inactive menu items.
33810          *
33811          * ui-sref-active can live on the same element as ui-sref or on a parent element. The first
33812          * ui-sref-active found at the same level or above the ui-sref will be used.
33813          *
33814          * Will activate when the ui-sref's target state or any child state is active. If you
33815          * need to activate only when the ui-sref target state is active and *not* any of
33816          * it's children, then you will use
33817          * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq}
33818          *
33819          * @example
33820          * Given the following template:
33821          * <pre>
33822          * <ul>
33823          *   <li ui-sref-active="active" class="item">
33824          *     <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
33825          *   </li>
33826          * </ul>
33827          * </pre>
33828          *
33829          *
33830          * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins",
33831          * the resulting HTML will appear as (note the 'active' class):
33832          * <pre>
33833          * <ul>
33834          *   <li ui-sref-active="active" class="item active">
33835          *     <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
33836          *   </li>
33837          * </ul>
33838          * </pre>
33839          *
33840          * The class name is interpolated **once** during the directives link time (any further changes to the
33841          * interpolated value are ignored).
33842          *
33843          * Multiple classes may be specified in a space-separated format:
33844          * <pre>
33845          * <ul>
33846          *   <li ui-sref-active='class1 class2 class3'>
33847          *     <a ui-sref="app.user">link</a>
33848          *   </li>
33849          * </ul>
33850          * </pre>
33851 <<<<<<< HEAD
33852          *
33853          * It is also possible to pass ui-sref-active an expression that evaluates
33854          * to an object hash, whose keys represent active class names and whose
33855          * values represent the respective state names/globs.
33856          * ui-sref-active will match if the current active state **includes** any of
33857          * the specified state names/globs, even the abstract ones.
33858          *
33859          * @Example
33860          * Given the following template, with "admin" being an abstract state:
33861          * <pre>
33862          * <div ui-sref-active="{'active': 'admin.*'}">
33863          *   <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
33864          * </div>
33865          * </pre>
33866          *
33867          * When the current state is "admin.roles" the "active" class will be applied
33868          * to both the <div> and <a> elements. It is important to note that the state
33869          * names/globs passed to ui-sref-active shadow the state provided by ui-sref.
33870 =======
33871 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33872          */
33873
33874         /**
33875          * @ngdoc directive
33876          * @name ui.router.state.directive:ui-sref-active-eq
33877          *
33878          * @requires ui.router.state.$state
33879          * @requires ui.router.state.$stateParams
33880          * @requires $interpolate
33881          *
33882          * @restrict A
33883          *
33884          * @description
33885          * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate
33886          * when the exact target state used in the `ui-sref` is active; no child states.
33887          *
33888          */
33889         $StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];
33890         function $StateRefActiveDirective($state, $stateParams, $interpolate) {
33891           return  {
33892             restrict: "A",
33893 <<<<<<< HEAD
33894             controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) {
33895               var states = [], activeClasses = {}, activeEqClass, uiSrefActive;
33896 =======
33897             controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
33898               var states = [], activeClass;
33899 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
33900
33901               // There probably isn't much point in $observing this
33902               // uiSrefActive and uiSrefActiveEq share the same directive object with some
33903               // slight difference in logic routing
33904 <<<<<<< HEAD
33905               activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);
33906
33907               try {
33908                 uiSrefActive = $scope.$eval($attrs.uiSrefActive);
33909               } catch (e) {
33910                 // Do nothing. uiSrefActive is not a valid expression.
33911                 // Fall back to using $interpolate below
33912               }
33913               uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
33914               if (isObject(uiSrefActive)) {
33915                 forEach(uiSrefActive, function(stateOrName, activeClass) {
33916                   if (isString(stateOrName)) {
33917                     var ref = parseStateRef(stateOrName, $state.current.name);
33918                     addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
33919                   }
33920                 });
33921               }
33922
33923               // Allow uiSref to communicate with uiSrefActive[Equals]
33924               this.$$addStateInfo = function (newState, newParams) {
33925                 // we already got an explicit state provided by ui-sref-active, so we
33926                 // shadow the one that comes from ui-sref
33927                 if (isObject(uiSrefActive) && states.length > 0) {
33928                   return;
33929                 }
33930                 addState(newState, newParams, uiSrefActive);
33931                 update();
33932               };
33933
33934               $scope.$on('$stateChangeSuccess', update);
33935
33936               function addState(stateName, stateParams, activeClass) {
33937                 var state = $state.get(stateName, stateContext($element));
33938                 var stateHash = createStateHash(stateName, stateParams);
33939
33940                 states.push({
33941                   state: state || { name: stateName },
33942                   params: stateParams,
33943                   hash: stateHash
33944                 });
33945
33946                 activeClasses[stateHash] = activeClass;
33947               }
33948
33949               /**
33950                * @param {string} state
33951                * @param {Object|string} [params]
33952                * @return {string}
33953                */
33954               function createStateHash(state, params) {
33955                 if (!isString(state)) {
33956                   throw new Error('state should be a string');
33957                 }
33958                 if (isObject(params)) {
33959                   return state + toJson(params);
33960                 }
33961                 params = $scope.$eval(params);
33962                 if (isObject(params)) {
33963                   return state + toJson(params);
33964                 }
33965                 return state;
33966               }
33967
33968               // Update route state
33969               function update() {
33970                 for (var i = 0; i < states.length; i++) {
33971                   if (anyMatch(states[i].state, states[i].params)) {
33972                     addClass($element, activeClasses[states[i].hash]);
33973                   } else {
33974                     removeClass($element, activeClasses[states[i].hash]);
33975                   }
33976
33977                   if (exactMatch(states[i].state, states[i].params)) {
33978                     addClass($element, activeEqClass);
33979                   } else {
33980                     removeClass($element, activeEqClass);
33981                   }
33982                 }
33983               }
33984
33985               function addClass(el, className) { $timeout(function () { el.addClass(className); }); }
33986               function removeClass(el, className) { el.removeClass(className); }
33987               function anyMatch(state, params) { return $state.includes(state.name, params); }
33988               function exactMatch(state, params) { return $state.is(state.name, params); }
33989
33990               update();
33991 =======
33992               activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || '', false)($scope);
33993
33994               // Allow uiSref to communicate with uiSrefActive[Equals]
33995               this.$$addStateInfo = function (newState, newParams) {
33996                 var state = $state.get(newState, stateContext($element));
33997
33998                 states.push({
33999                   state: state || { name: newState },
34000                   params: newParams
34001                 });
34002
34003                 update();
34004               };
34005
34006               $scope.$on('$stateChangeSuccess', update);
34007
34008               // Update route state
34009               function update() {
34010                 if (anyMatch()) {
34011                   $element.addClass(activeClass);
34012                 } else {
34013                   $element.removeClass(activeClass);
34014                 }
34015               }
34016
34017               function anyMatch() {
34018                 for (var i = 0; i < states.length; i++) {
34019                   if (isMatch(states[i].state, states[i].params)) {
34020                     return true;
34021                   }
34022                 }
34023                 return false;
34024               }
34025
34026               function isMatch(state, params) {
34027                 if (typeof $attrs.uiSrefActiveEq !== 'undefined') {
34028                   return $state.is(state.name, params);
34029                 } else {
34030                   return $state.includes(state.name, params);
34031                 }
34032               }
34033 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34034             }]
34035           };
34036         }
34037
34038         angular.module('ui.router.state')
34039           .directive('uiSref', $StateRefDirective)
34040           .directive('uiSrefActive', $StateRefActiveDirective)
34041 <<<<<<< HEAD
34042           .directive('uiSrefActiveEq', $StateRefActiveDirective)
34043           .directive('uiState', $StateRefDynamicDirective);
34044 =======
34045           .directive('uiSrefActiveEq', $StateRefActiveDirective);
34046 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34047
34048         /**
34049          * @ngdoc filter
34050          * @name ui.router.state.filter:isState
34051          *
34052          * @requires ui.router.state.$state
34053          *
34054          * @description
34055          * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}.
34056          */
34057         $IsStateFilter.$inject = ['$state'];
34058         function $IsStateFilter($state) {
34059 <<<<<<< HEAD
34060           var isFilter = function (state, params) {
34061             return $state.is(state, params);
34062 =======
34063           var isFilter = function (state) {
34064             return $state.is(state);
34065 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34066           };
34067           isFilter.$stateful = true;
34068           return isFilter;
34069         }
34070
34071         /**
34072          * @ngdoc filter
34073          * @name ui.router.state.filter:includedByState
34074          *
34075          * @requires ui.router.state.$state
34076          *
34077          * @description
34078          * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}.
34079          */
34080         $IncludedByStateFilter.$inject = ['$state'];
34081         function $IncludedByStateFilter($state) {
34082 <<<<<<< HEAD
34083           var includesFilter = function (state, params, options) {
34084             return $state.includes(state, params, options);
34085 =======
34086           var includesFilter = function (state) {
34087             return $state.includes(state);
34088 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34089           };
34090           includesFilter.$stateful = true;
34091           return  includesFilter;
34092         }
34093
34094         angular.module('ui.router.state')
34095           .filter('isState', $IsStateFilter)
34096           .filter('includedByState', $IncludedByStateFilter);
34097         })(window, window.angular);
34098
34099 /***/ },
34100 /* 4 */
34101 /***/ function(module, exports, __webpack_require__) {
34102
34103         __webpack_require__(5);
34104         module.exports = 'ngResource';
34105
34106
34107 /***/ },
34108 /* 5 */
34109 /***/ function(module, exports) {
34110
34111         /**
34112 <<<<<<< HEAD
34113          * @license AngularJS v1.6.2
34114          * (c) 2010-2017 Google, Inc. http://angularjs.org
34115          * License: MIT
34116          */
34117         (function(window, angular) {'use strict';
34118 =======
34119          * @license AngularJS v1.4.8
34120          * (c) 2010-2015 Google, Inc. http://angularjs.org
34121          * License: MIT
34122          */
34123         (function(window, angular, undefined) {'use strict';
34124 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34125
34126         var $resourceMinErr = angular.$$minErr('$resource');
34127
34128         // Helper functions and regex to lookup a dotted path on an object
34129         // stopping at undefined/null.  The path must be composed of ASCII
34130         // identifiers (just like $parse)
34131         var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;
34132
34133         function isValidDottedPath(path) {
34134           return (path != null && path !== '' && path !== 'hasOwnProperty' &&
34135               MEMBER_NAME_REGEX.test('.' + path));
34136         }
34137
34138         function lookupDottedPath(obj, path) {
34139           if (!isValidDottedPath(path)) {
34140             throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path);
34141           }
34142           var keys = path.split('.');
34143           for (var i = 0, ii = keys.length; i < ii && angular.isDefined(obj); i++) {
34144             var key = keys[i];
34145             obj = (obj !== null) ? obj[key] : undefined;
34146           }
34147           return obj;
34148         }
34149
34150         /**
34151          * Create a shallow copy of an object and clear other fields from the destination
34152          */
34153         function shallowClearAndCopy(src, dst) {
34154           dst = dst || {};
34155
34156           angular.forEach(dst, function(value, key) {
34157             delete dst[key];
34158           });
34159
34160           for (var key in src) {
34161             if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
34162               dst[key] = src[key];
34163             }
34164           }
34165
34166           return dst;
34167         }
34168
34169         /**
34170          * @ngdoc module
34171          * @name ngResource
34172          * @description
34173          *
34174          * # ngResource
34175          *
34176          * The `ngResource` module provides interaction support with RESTful services
34177          * via the $resource service.
34178          *
34179          *
34180          * <div doc-module-components="ngResource"></div>
34181          *
34182 <<<<<<< HEAD
34183          * See {@link ngResource.$resourceProvider} and {@link ngResource.$resource} for usage.
34184          */
34185
34186         /**
34187          * @ngdoc provider
34188          * @name $resourceProvider
34189          *
34190          * @description
34191          *
34192          * Use `$resourceProvider` to change the default behavior of the {@link ngResource.$resource}
34193          * service.
34194          *
34195          * ## Dependencies
34196          * Requires the {@link ngResource } module to be installed.
34197          *
34198 =======
34199          * See {@link ngResource.$resource `$resource`} for usage.
34200 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34201          */
34202
34203         /**
34204          * @ngdoc service
34205          * @name $resource
34206          * @requires $http
34207 <<<<<<< HEAD
34208          * @requires ng.$log
34209          * @requires $q
34210          * @requires ng.$timeout
34211 =======
34212 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34213          *
34214          * @description
34215          * A factory which creates a resource object that lets you interact with
34216          * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
34217          *
34218          * The returned resource object has action methods which provide high-level behaviors without
34219          * the need to interact with the low level {@link ng.$http $http} service.
34220          *
34221          * Requires the {@link ngResource `ngResource`} module to be installed.
34222          *
34223          * By default, trailing slashes will be stripped from the calculated URLs,
34224          * which can pose problems with server backends that do not expect that
34225          * behavior.  This can be disabled by configuring the `$resourceProvider` like
34226          * this:
34227          *
34228          * ```js
34229              app.config(['$resourceProvider', function($resourceProvider) {
34230                // Don't strip trailing slashes from calculated URLs
34231                $resourceProvider.defaults.stripTrailingSlashes = false;
34232              }]);
34233          * ```
34234          *
34235          * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
34236          *   `/user/:username`. If you are using a URL with a port number (e.g.
34237          *   `http://example.com:8080/api`), it will be respected.
34238          *
34239          *   If you are using a url with a suffix, just add the suffix, like this:
34240          *   `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')`
34241          *   or even `$resource('http://example.com/resource/:resource_id.:format')`
34242          *   If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
34243          *   collapsed down to a single `.`.  If you need this sequence to appear and not collapse then you
34244          *   can escape it with `/\.`.
34245          *
34246          * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
34247 <<<<<<< HEAD
34248          *   `actions` methods. If a parameter value is a function, it will be called every time
34249          *   a param value needs to be obtained for a request (unless the param was overridden). The function
34250          *   will be passed the current data value as an argument.
34251 =======
34252          *   `actions` methods. If any of the parameter value is a function, it will be executed every time
34253          *   when a param value needs to be obtained for a request (unless the param was overridden).
34254 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34255          *
34256          *   Each key value in the parameter object is first bound to url template if present and then any
34257          *   excess keys are appended to the url search query after the `?`.
34258          *
34259          *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
34260          *   URL `/path/greet?salutation=Hello`.
34261          *
34262 <<<<<<< HEAD
34263          *   If the parameter value is prefixed with `@`, then the value for that parameter will be
34264          *   extracted from the corresponding property on the `data` object (provided when calling a
34265          *   "non-GET" action method).
34266          *   For example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of
34267          *   `someParam` will be `data.someProp`.
34268          *   Note that the parameter will be ignored, when calling a "GET" action method (i.e. an action
34269          *   method that does not accept a request body)
34270          *
34271          * @param {Object.<Object>=} actions Hash with declaration of custom actions that will be available
34272          *   in addition to the default set of resource actions (see below). If a custom action has the same
34273          *   key as a default action (e.g. `save`), then the default action will be *overwritten*, and not
34274          *   extended.
34275          *
34276          *   The declaration should be created in the format of {@link ng.$http#usage $http.config}:
34277 =======
34278          *   If the parameter value is prefixed with `@` then the value for that parameter will be extracted
34279          *   from the corresponding property on the `data` object (provided when calling an action method).  For
34280          *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`
34281          *   will be `data.someProp`.
34282          *
34283          * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend
34284          *   the default set of resource actions. The declaration should be created in the format of {@link
34285          *   ng.$http#usage $http.config}:
34286 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34287          *
34288          *       {action1: {method:?, params:?, isArray:?, headers:?, ...},
34289          *        action2: {method:?, params:?, isArray:?, headers:?, ...},
34290          *        ...}
34291          *
34292          *   Where:
34293          *
34294          *   - **`action`** – {string} – The name of action. This name becomes the name of the method on
34295          *     your resource object.
34296          *   - **`method`** – {string} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`,
34297          *     `DELETE`, `JSONP`, etc).
34298          *   - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of
34299 <<<<<<< HEAD
34300          *     the parameter value is a function, it will be called every time when a param value needs to
34301          *     be obtained for a request (unless the param was overridden). The function will be passed the
34302          *     current data value as an argument.
34303 =======
34304          *     the parameter value is a function, it will be executed every time when a param value needs to
34305          *     be obtained for a request (unless the param was overridden).
34306 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34307          *   - **`url`** – {string} – action specific `url` override. The url templating is supported just
34308          *     like for the resource-level urls.
34309          *   - **`isArray`** – {boolean=} – If true then the returned object for this action is an array,
34310          *     see `returns` section.
34311          *   - **`transformRequest`** –
34312          *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
34313          *     transform function or an array of such functions. The transform function takes the http
34314          *     request body and headers and returns its transformed (typically serialized) version.
34315          *     By default, transformRequest will contain one function that checks if the request data is
34316 <<<<<<< HEAD
34317          *     an object and serializes it using `angular.toJson`. To prevent this behavior, set
34318          *     `transformRequest` to an empty array: `transformRequest: []`
34319          *   - **`transformResponse`** –
34320          *     `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
34321          *     transform function or an array of such functions. The transform function takes the http
34322          *     response body, headers and status and returns its transformed (typically deserialized)
34323          *     version.
34324          *     By default, transformResponse will contain one function that checks if the response looks
34325          *     like a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior,
34326          *     set `transformResponse` to an empty array: `transformResponse: []`
34327 =======
34328          *     an object and serializes to using `angular.toJson`. To prevent this behavior, set
34329          *     `transformRequest` to an empty array: `transformRequest: []`
34330          *   - **`transformResponse`** –
34331          *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
34332          *     transform function or an array of such functions. The transform function takes the http
34333          *     response body and headers and returns its transformed (typically deserialized) version.
34334          *     By default, transformResponse will contain one function that checks if the response looks like
34335          *     a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set
34336          *     `transformResponse` to an empty array: `transformResponse: []`
34337 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34338          *   - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
34339          *     GET request, otherwise if a cache instance built with
34340          *     {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
34341          *     caching.
34342 <<<<<<< HEAD
34343          *   - **`timeout`** – `{number}` – timeout in milliseconds.<br />
34344          *     **Note:** In contrast to {@link ng.$http#usage $http.config}, {@link ng.$q promises} are
34345          *     **not** supported in $resource, because the same value would be used for multiple requests.
34346          *     If you are looking for a way to cancel requests, you should use the `cancellable` option.
34347          *   - **`cancellable`** – `{boolean}` – if set to true, the request made by a "non-instance" call
34348          *     will be cancelled (if not already completed) by calling `$cancelRequest()` on the call's
34349          *     return value. Calling `$cancelRequest()` for a non-cancellable or an already
34350          *     completed/cancelled request will have no effect.<br />
34351 =======
34352          *   - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that
34353          *     should abort the request when resolved.
34354 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34355          *   - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the
34356          *     XHR object. See
34357          *     [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)
34358          *     for more information.
34359          *   - **`responseType`** - `{string}` - see
34360          *     [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
34361          *   - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
34362          *     `response` and `responseError`. Both `response` and `responseError` interceptors get called
34363          *     with `http response` object. See {@link ng.$http $http interceptors}.
34364          *
34365          * @param {Object} options Hash with custom settings that should extend the
34366 <<<<<<< HEAD
34367          *   default `$resourceProvider` behavior.  The supported options are:
34368          *
34369          *   - **`stripTrailingSlashes`** – {boolean} – If true then the trailing
34370          *   slashes from any calculated URL will be stripped. (Defaults to true.)
34371          *   - **`cancellable`** – {boolean} – If true, the request made by a "non-instance" call will be
34372          *   cancelled (if not already completed) by calling `$cancelRequest()` on the call's return value.
34373          *   This can be overwritten per action. (Defaults to false.)
34374 =======
34375          *   default `$resourceProvider` behavior.  The only supported option is
34376          *
34377          *   Where:
34378          *
34379          *   - **`stripTrailingSlashes`** – {boolean} – If true then the trailing
34380          *   slashes from any calculated URL will be stripped. (Defaults to true.)
34381 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34382          *
34383          * @returns {Object} A resource "class" object with methods for the default set of resource actions
34384          *   optionally extended with custom `actions`. The default set contains these actions:
34385          *   ```js
34386          *   { 'get':    {method:'GET'},
34387          *     'save':   {method:'POST'},
34388          *     'query':  {method:'GET', isArray:true},
34389          *     'remove': {method:'DELETE'},
34390          *     'delete': {method:'DELETE'} };
34391          *   ```
34392          *
34393          *   Calling these methods invoke an {@link ng.$http} with the specified http method,
34394          *   destination and parameters. When the data is returned from the server then the object is an
34395          *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it
34396          *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
34397          *   read, update, delete) on server-side data like this:
34398          *   ```js
34399          *   var User = $resource('/user/:userId', {userId:'@id'});
34400          *   var user = User.get({userId:123}, function() {
34401          *     user.abc = true;
34402          *     user.$save();
34403          *   });
34404          *   ```
34405          *
34406          *   It is important to realize that invoking a $resource object method immediately returns an
34407          *   empty reference (object or array depending on `isArray`). Once the data is returned from the
34408          *   server the existing reference is populated with the actual data. This is a useful trick since
34409          *   usually the resource is assigned to a model which is then rendered by the view. Having an empty
34410          *   object results in no rendering, once the data arrives from the server then the object is
34411          *   populated with the data and the view automatically re-renders itself showing the new data. This
34412          *   means that in most cases one never has to write a callback function for the action methods.
34413          *
34414          *   The action methods on the class object or instance object can be invoked with the following
34415          *   parameters:
34416          *
34417          *   - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
34418          *   - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
34419          *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`
34420          *
34421          *
34422 <<<<<<< HEAD
34423          *   Success callback is called with (value (Object|Array), responseHeaders (Function),
34424          *   status (number), statusText (string)) arguments, where the value is the populated resource
34425          *   instance or collection object. The error callback is called with (httpResponse) argument.
34426 =======
34427          *   Success callback is called with (value, responseHeaders) arguments, where the value is
34428          *   the populated resource instance or collection object. The error callback is called
34429          *   with (httpResponse) argument.
34430 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34431          *
34432          *   Class actions return empty instance (with additional properties below).
34433          *   Instance actions return promise of the action.
34434          *
34435 <<<<<<< HEAD
34436          *   The Resource instances and collections have these additional properties:
34437 =======
34438          *   The Resource instances and collection have these additional properties:
34439 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34440          *
34441          *   - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
34442          *     instance or collection.
34443          *
34444          *     On success, the promise is resolved with the same resource instance or collection object,
34445          *     updated with data from server. This makes it easy to use in
34446          *     {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view
34447          *     rendering until the resource(s) are loaded.
34448          *
34449 <<<<<<< HEAD
34450          *     On failure, the promise is rejected with the {@link ng.$http http response} object, without
34451 =======
34452          *     On failure, the promise is resolved with the {@link ng.$http http response} object, without
34453 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34454          *     the `resource` property.
34455          *
34456          *     If an interceptor object was provided, the promise will instead be resolved with the value
34457          *     returned by the interceptor.
34458          *
34459          *   - `$resolved`: `true` after first server interaction is completed (either with success or
34460          *      rejection), `false` before that. Knowing if the Resource has been resolved is useful in
34461          *      data-binding.
34462          *
34463 <<<<<<< HEAD
34464          *   The Resource instances and collections have these additional methods:
34465          *
34466          *   - `$cancelRequest`: If there is a cancellable, pending request related to the instance or
34467          *      collection, calling this method will abort the request.
34468          *
34469          *   The Resource instances have these additional methods:
34470          *
34471          *   - `toJSON`: It returns a simple object without any of the extra properties added as part of
34472          *     the Resource API. This object can be serialized through {@link angular.toJson} safely
34473          *     without attaching Angular-specific fields. Notice that `JSON.stringify` (and
34474          *     `angular.toJson`) automatically use this method when serializing a Resource instance
34475          *     (see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior)).
34476          *
34477 =======
34478 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34479          * @example
34480          *
34481          * # Credit card resource
34482          *
34483          * ```js
34484              // Define CreditCard class
34485              var CreditCard = $resource('/user/:userId/card/:cardId',
34486               {userId:123, cardId:'@id'}, {
34487                charge: {method:'POST', params:{charge:true}}
34488               });
34489
34490              // We can retrieve a collection from the server
34491              var cards = CreditCard.query(function() {
34492                // GET: /user/123/card
34493                // server returns: [ {id:456, number:'1234', name:'Smith'} ];
34494
34495                var card = cards[0];
34496                // each item is an instance of CreditCard
34497                expect(card instanceof CreditCard).toEqual(true);
34498                card.name = "J. Smith";
34499                // non GET methods are mapped onto the instances
34500                card.$save();
34501                // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
34502                // server returns: {id:456, number:'1234', name: 'J. Smith'};
34503
34504                // our custom method is mapped as well.
34505                card.$charge({amount:9.99});
34506                // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
34507              });
34508
34509              // we can create an instance as well
34510              var newCard = new CreditCard({number:'0123'});
34511              newCard.name = "Mike Smith";
34512              newCard.$save();
34513              // POST: /user/123/card {number:'0123', name:'Mike Smith'}
34514              // server returns: {id:789, number:'0123', name: 'Mike Smith'};
34515              expect(newCard.id).toEqual(789);
34516          * ```
34517          *
34518          * The object returned from this function execution is a resource "class" which has "static" method
34519          * for each action in the definition.
34520          *
34521          * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and
34522          * `headers`.
34523 <<<<<<< HEAD
34524          *
34525          * @example
34526          *
34527          * # User resource
34528          *
34529 =======
34530 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34531          * When the data is returned from the server then the object is an instance of the resource type and
34532          * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
34533          * operations (create, read, update, delete) on server-side data.
34534
34535            ```js
34536              var User = $resource('/user/:userId', {userId:'@id'});
34537              User.get({userId:123}, function(user) {
34538                user.abc = true;
34539                user.$save();
34540              });
34541            ```
34542          *
34543          * It's worth noting that the success callback for `get`, `query` and other methods gets passed
34544          * in the response that came from the server as well as $http header getter function, so one
34545          * could rewrite the above example and get access to http headers as:
34546          *
34547            ```js
34548              var User = $resource('/user/:userId', {userId:'@id'});
34549 <<<<<<< HEAD
34550              User.get({userId:123}, function(user, getResponseHeaders){
34551                user.abc = true;
34552                user.$save(function(user, putResponseHeaders) {
34553                  //user => saved user object
34554 =======
34555              User.get({userId:123}, function(u, getResponseHeaders){
34556                u.abc = true;
34557                u.$save(function(u, putResponseHeaders) {
34558                  //u => saved user object
34559 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34560                  //putResponseHeaders => $http header getter
34561                });
34562              });
34563            ```
34564          *
34565          * You can also access the raw `$http` promise via the `$promise` property on the object returned
34566          *
34567            ```
34568              var User = $resource('/user/:userId', {userId:'@id'});
34569              User.get({userId:123})
34570                  .$promise.then(function(user) {
34571                    $scope.user = user;
34572                  });
34573            ```
34574 <<<<<<< HEAD
34575          *
34576          * @example
34577          *
34578          * # Creating a custom 'PUT' request
34579          *
34580 =======
34581
34582          * # Creating a custom 'PUT' request
34583 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34584          * In this example we create a custom method on our resource to make a PUT request
34585          * ```js
34586          *    var app = angular.module('app', ['ngResource', 'ngRoute']);
34587          *
34588          *    // Some APIs expect a PUT request in the format URL/object/ID
34589          *    // Here we are creating an 'update' method
34590          *    app.factory('Notes', ['$resource', function($resource) {
34591          *    return $resource('/notes/:id', null,
34592          *        {
34593          *            'update': { method:'PUT' }
34594          *        });
34595          *    }]);
34596          *
34597          *    // In our controller we get the ID from the URL using ngRoute and $routeParams
34598          *    // We pass in $routeParams and our Notes factory along with $scope
34599          *    app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
34600                                               function($scope, $routeParams, Notes) {
34601          *    // First get a note object from the factory
34602          *    var note = Notes.get({ id:$routeParams.id });
34603          *    $id = note.id;
34604          *
34605          *    // Now call update passing in the ID first then the object you are updating
34606          *    Notes.update({ id:$id }, note);
34607          *
34608          *    // This will PUT /notes/ID with the note object in the request payload
34609          *    }]);
34610          * ```
34611 <<<<<<< HEAD
34612          *
34613          * @example
34614          *
34615          * # Cancelling requests
34616          *
34617          * If an action's configuration specifies that it is cancellable, you can cancel the request related
34618          * to an instance or collection (as long as it is a result of a "non-instance" call):
34619          *
34620            ```js
34621              // ...defining the `Hotel` resource...
34622              var Hotel = $resource('/api/hotel/:id', {id: '@id'}, {
34623                // Let's make the `query()` method cancellable
34624                query: {method: 'get', isArray: true, cancellable: true}
34625              });
34626
34627              // ...somewhere in the PlanVacationController...
34628              ...
34629              this.onDestinationChanged = function onDestinationChanged(destination) {
34630                // We don't care about any pending request for hotels
34631                // in a different destination any more
34632                this.availableHotels.$cancelRequest();
34633
34634                // Let's query for hotels in '<destination>'
34635                // (calls: /api/hotel?location=<destination>)
34636                this.availableHotels = Hotel.query({location: destination});
34637              };
34638            ```
34639          *
34640          */
34641         angular.module('ngResource', ['ng']).
34642           provider('$resource', function ResourceProvider() {
34643             var PROTOCOL_AND_IPV6_REGEX = /^https?:\/\/\[[^\]]*][^/]*/;
34644
34645             var provider = this;
34646
34647             /**
34648              * @ngdoc property
34649              * @name $resourceProvider#defaults
34650              * @description
34651              * Object containing default options used when creating `$resource` instances.
34652              *
34653              * The default values satisfy a wide range of usecases, but you may choose to overwrite any of
34654              * them to further customize your instances. The available properties are:
34655              *
34656              * - **stripTrailingSlashes** – `{boolean}` – If true, then the trailing slashes from any
34657              *   calculated URL will be stripped.<br />
34658              *   (Defaults to true.)
34659              * - **cancellable** – `{boolean}` – If true, the request made by a "non-instance" call will be
34660              *   cancelled (if not already completed) by calling `$cancelRequest()` on the call's return
34661              *   value. For more details, see {@link ngResource.$resource}. This can be overwritten per
34662              *   resource class or action.<br />
34663              *   (Defaults to false.)
34664              * - **actions** - `{Object.<Object>}` - A hash with default actions declarations. Actions are
34665              *   high-level methods corresponding to RESTful actions/methods on resources. An action may
34666              *   specify what HTTP method to use, what URL to hit, if the return value will be a single
34667              *   object or a collection (array) of objects etc. For more details, see
34668              *   {@link ngResource.$resource}. The actions can also be enhanced or overwritten per resource
34669              *   class.<br />
34670              *   The default actions are:
34671              *   ```js
34672              *   {
34673              *     get: {method: 'GET'},
34674              *     save: {method: 'POST'},
34675              *     query: {method: 'GET', isArray: true},
34676              *     remove: {method: 'DELETE'},
34677              *     delete: {method: 'DELETE'}
34678              *   }
34679              *   ```
34680              *
34681              * #### Example
34682              *
34683              * For example, you can specify a new `update` action that uses the `PUT` HTTP verb:
34684              *
34685              * ```js
34686              *   angular.
34687              *     module('myApp').
34688              *     config(['$resourceProvider', function ($resourceProvider) {
34689              *       $resourceProvider.defaults.actions.update = {
34690              *         method: 'PUT'
34691              *       };
34692              *     });
34693              * ```
34694              *
34695              * Or you can even overwrite the whole `actions` list and specify your own:
34696              *
34697              * ```js
34698              *   angular.
34699              *     module('myApp').
34700              *     config(['$resourceProvider', function ($resourceProvider) {
34701              *       $resourceProvider.defaults.actions = {
34702              *         create: {method: 'POST'},
34703              *         get:    {method: 'GET'},
34704              *         getAll: {method: 'GET', isArray:true},
34705              *         update: {method: 'PUT'},
34706              *         delete: {method: 'DELETE'}
34707              *       };
34708              *     });
34709              * ```
34710              *
34711              */
34712 =======
34713          */
34714         angular.module('ngResource', ['ng']).
34715           provider('$resource', function() {
34716             var PROTOCOL_AND_DOMAIN_REGEX = /^https?:\/\/[^\/]*/;
34717             var provider = this;
34718
34719 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34720             this.defaults = {
34721               // Strip slashes by default
34722               stripTrailingSlashes: true,
34723
34724 <<<<<<< HEAD
34725               // Make non-instance requests cancellable (via `$cancelRequest()`)
34726               cancellable: false,
34727
34728 =======
34729 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34730               // Default actions configuration
34731               actions: {
34732                 'get': {method: 'GET'},
34733                 'save': {method: 'POST'},
34734                 'query': {method: 'GET', isArray: true},
34735                 'remove': {method: 'DELETE'},
34736                 'delete': {method: 'DELETE'}
34737               }
34738             };
34739
34740 <<<<<<< HEAD
34741             this.$get = ['$http', '$log', '$q', '$timeout', function($http, $log, $q, $timeout) {
34742
34743               var noop = angular.noop,
34744                   forEach = angular.forEach,
34745                   extend = angular.extend,
34746                   copy = angular.copy,
34747                   isArray = angular.isArray,
34748                   isDefined = angular.isDefined,
34749                   isFunction = angular.isFunction,
34750                   isNumber = angular.isNumber,
34751                   encodeUriQuery = angular.$$encodeUriQuery,
34752                   encodeUriSegment = angular.$$encodeUriSegment;
34753 =======
34754             this.$get = ['$http', '$q', function($http, $q) {
34755
34756               var noop = angular.noop,
34757                 forEach = angular.forEach,
34758                 extend = angular.extend,
34759                 copy = angular.copy,
34760                 isFunction = angular.isFunction;
34761
34762               /**
34763                * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
34764                * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set
34765                * (pchar) allowed in path segments:
34766                *    segment       = *pchar
34767                *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
34768                *    pct-encoded   = "%" HEXDIG HEXDIG
34769                *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
34770                *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
34771                *                     / "*" / "+" / "," / ";" / "="
34772                */
34773               function encodeUriSegment(val) {
34774                 return encodeUriQuery(val, true).
34775                   replace(/%26/gi, '&').
34776                   replace(/%3D/gi, '=').
34777                   replace(/%2B/gi, '+');
34778               }
34779
34780
34781               /**
34782                * This method is intended for encoding *key* or *value* parts of query component. We need a
34783                * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't
34784                * have to be encoded per http://tools.ietf.org/html/rfc3986:
34785                *    query       = *( pchar / "/" / "?" )
34786                *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
34787                *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
34788                *    pct-encoded   = "%" HEXDIG HEXDIG
34789                *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
34790                *                     / "*" / "+" / "," / ";" / "="
34791                */
34792               function encodeUriQuery(val, pctEncodeSpaces) {
34793                 return encodeURIComponent(val).
34794                   replace(/%40/gi, '@').
34795                   replace(/%3A/gi, ':').
34796                   replace(/%24/g, '$').
34797                   replace(/%2C/gi, ',').
34798                   replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
34799               }
34800 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34801
34802               function Route(template, defaults) {
34803                 this.template = template;
34804                 this.defaults = extend({}, provider.defaults, defaults);
34805                 this.urlParams = {};
34806               }
34807
34808               Route.prototype = {
34809                 setUrlParams: function(config, params, actionUrl) {
34810                   var self = this,
34811                     url = actionUrl || self.template,
34812                     val,
34813                     encodedVal,
34814 <<<<<<< HEAD
34815                     protocolAndIpv6 = '';
34816
34817                   var urlParams = self.urlParams = Object.create(null);
34818                   forEach(url.split(/\W/), function(param) {
34819                     if (param === 'hasOwnProperty') {
34820                       throw $resourceMinErr('badname', 'hasOwnProperty is not a valid parameter name.');
34821                     }
34822                     if (!(new RegExp('^\\d+$').test(param)) && param &&
34823                       (new RegExp('(^|[^\\\\]):' + param + '(\\W|$)').test(url))) {
34824                       urlParams[param] = {
34825                         isQueryParamValue: (new RegExp('\\?.*=:' + param + '(?:\\W|$)')).test(url)
34826                       };
34827                     }
34828                   });
34829                   url = url.replace(/\\:/g, ':');
34830                   url = url.replace(PROTOCOL_AND_IPV6_REGEX, function(match) {
34831                     protocolAndIpv6 = match;
34832 =======
34833                     protocolAndDomain = '';
34834
34835                   var urlParams = self.urlParams = {};
34836                   forEach(url.split(/\W/), function(param) {
34837                     if (param === 'hasOwnProperty') {
34838                       throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name.");
34839                     }
34840                     if (!(new RegExp("^\\d+$").test(param)) && param &&
34841                       (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
34842                       urlParams[param] = true;
34843                     }
34844                   });
34845                   url = url.replace(/\\:/g, ':');
34846                   url = url.replace(PROTOCOL_AND_DOMAIN_REGEX, function(match) {
34847                     protocolAndDomain = match;
34848 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34849                     return '';
34850                   });
34851
34852                   params = params || {};
34853 <<<<<<< HEAD
34854                   forEach(self.urlParams, function(paramInfo, urlParam) {
34855                     val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
34856                     if (isDefined(val) && val !== null) {
34857                       if (paramInfo.isQueryParamValue) {
34858                         encodedVal = encodeUriQuery(val, true);
34859                       } else {
34860                         encodedVal = encodeUriSegment(val);
34861                       }
34862                       url = url.replace(new RegExp(':' + urlParam + '(\\W|$)', 'g'), function(match, p1) {
34863                         return encodedVal + p1;
34864                       });
34865                     } else {
34866                       url = url.replace(new RegExp('(/?):' + urlParam + '(\\W|$)', 'g'), function(match,
34867                           leadingSlashes, tail) {
34868                         if (tail.charAt(0) === '/') {
34869 =======
34870                   forEach(self.urlParams, function(_, urlParam) {
34871                     val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
34872                     if (angular.isDefined(val) && val !== null) {
34873                       encodedVal = encodeUriSegment(val);
34874                       url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) {
34875                         return encodedVal + p1;
34876                       });
34877                     } else {
34878                       url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
34879                           leadingSlashes, tail) {
34880                         if (tail.charAt(0) == '/') {
34881 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34882                           return tail;
34883                         } else {
34884                           return leadingSlashes + tail;
34885                         }
34886                       });
34887                     }
34888                   });
34889
34890                   // strip trailing slashes and set the url (unless this behavior is specifically disabled)
34891                   if (self.defaults.stripTrailingSlashes) {
34892                     url = url.replace(/\/+$/, '') || '/';
34893                   }
34894
34895 <<<<<<< HEAD
34896                   // Collapse `/.` if found in the last URL path segment before the query.
34897                   // E.g. `http://url.com/id/.format?q=x` becomes `http://url.com/id.format?q=x`.
34898                   url = url.replace(/\/\.(?=\w+($|\?))/, '.');
34899                   // Replace escaped `/\.` with `/.`.
34900                   // (If `\.` comes from a param value, it will be encoded as `%5C.`.)
34901                   config.url = protocolAndIpv6 + url.replace(/\/(\\|%5C)\./, '/.');
34902 =======
34903                   // then replace collapse `/.` if found in the last URL path segment before the query
34904                   // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`
34905                   url = url.replace(/\/\.(?=\w+($|\?))/, '.');
34906                   // replace escaped `/\.` with `/.`
34907                   config.url = protocolAndDomain + url.replace(/\/\\\./, '/.');
34908 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34909
34910
34911                   // set params - delegate param encoding to $http
34912                   forEach(params, function(value, key) {
34913                     if (!self.urlParams[key]) {
34914                       config.params = config.params || {};
34915                       config.params[key] = value;
34916                     }
34917                   });
34918                 }
34919               };
34920
34921
34922               function resourceFactory(url, paramDefaults, actions, options) {
34923                 var route = new Route(url, options);
34924
34925                 actions = extend({}, provider.defaults.actions, actions);
34926
34927                 function extractParams(data, actionParams) {
34928                   var ids = {};
34929                   actionParams = extend({}, paramDefaults, actionParams);
34930                   forEach(actionParams, function(value, key) {
34931 <<<<<<< HEAD
34932                     if (isFunction(value)) { value = value(data); }
34933                     ids[key] = value && value.charAt && value.charAt(0) === '@' ?
34934 =======
34935                     if (isFunction(value)) { value = value(); }
34936                     ids[key] = value && value.charAt && value.charAt(0) == '@' ?
34937 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34938                       lookupDottedPath(data, value.substr(1)) : value;
34939                   });
34940                   return ids;
34941                 }
34942
34943                 function defaultResponseInterceptor(response) {
34944                   return response.resource;
34945                 }
34946
34947                 function Resource(value) {
34948                   shallowClearAndCopy(value || {}, this);
34949                 }
34950
34951                 Resource.prototype.toJSON = function() {
34952                   var data = extend({}, this);
34953                   delete data.$promise;
34954                   delete data.$resolved;
34955 <<<<<<< HEAD
34956                   delete data.$cancelRequest;
34957 =======
34958 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34959                   return data;
34960                 };
34961
34962                 forEach(actions, function(action, name) {
34963                   var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
34964 <<<<<<< HEAD
34965                   var numericTimeout = action.timeout;
34966                   var cancellable = isDefined(action.cancellable) ?
34967                       action.cancellable : route.defaults.cancellable;
34968
34969                   if (numericTimeout && !isNumber(numericTimeout)) {
34970                     $log.debug('ngResource:\n' +
34971                                '  Only numeric values are allowed as `timeout`.\n' +
34972                                '  Promises are not supported in $resource, because the same value would ' +
34973                                'be used for multiple requests. If you are looking for a way to cancel ' +
34974                                'requests, you should use the `cancellable` option.');
34975                     delete action.timeout;
34976                     numericTimeout = null;
34977                   }
34978 =======
34979 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34980
34981                   Resource[name] = function(a1, a2, a3, a4) {
34982                     var params = {}, data, success, error;
34983
34984 <<<<<<< HEAD
34985 =======
34986                     /* jshint -W086 */ /* (purposefully fall through case statements) */
34987 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34988                     switch (arguments.length) {
34989                       case 4:
34990                         error = a4;
34991                         success = a3;
34992 <<<<<<< HEAD
34993                         // falls through
34994 =======
34995                       //fallthrough
34996 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
34997                       case 3:
34998                       case 2:
34999                         if (isFunction(a2)) {
35000                           if (isFunction(a1)) {
35001                             success = a1;
35002                             error = a2;
35003                             break;
35004                           }
35005
35006                           success = a2;
35007                           error = a3;
35008 <<<<<<< HEAD
35009                           // falls through
35010 =======
35011                           //fallthrough
35012 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35013                         } else {
35014                           params = a1;
35015                           data = a2;
35016                           success = a3;
35017                           break;
35018                         }
35019 <<<<<<< HEAD
35020                         // falls through
35021 =======
35022 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35023                       case 1:
35024                         if (isFunction(a1)) success = a1;
35025                         else if (hasBody) data = a1;
35026                         else params = a1;
35027                         break;
35028                       case 0: break;
35029                       default:
35030                         throw $resourceMinErr('badargs',
35031 <<<<<<< HEAD
35032                           'Expected up to 4 arguments [params, data, success, error], got {0} arguments',
35033                           arguments.length);
35034                     }
35035 =======
35036                           "Expected up to 4 arguments [params, data, success, error], got {0} arguments",
35037                           arguments.length);
35038                     }
35039                     /* jshint +W086 */ /* (purposefully fall through case statements) */
35040 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35041
35042                     var isInstanceCall = this instanceof Resource;
35043                     var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
35044                     var httpConfig = {};
35045                     var responseInterceptor = action.interceptor && action.interceptor.response ||
35046                       defaultResponseInterceptor;
35047                     var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
35048                       undefined;
35049 <<<<<<< HEAD
35050                     var hasError = !!error;
35051                     var hasResponseErrorInterceptor = !!responseErrorInterceptor;
35052                     var timeoutDeferred;
35053                     var numericTimeoutPromise;
35054 =======
35055 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35056
35057                     forEach(action, function(value, key) {
35058                       switch (key) {
35059                         default:
35060                           httpConfig[key] = copy(value);
35061                           break;
35062                         case 'params':
35063                         case 'isArray':
35064                         case 'interceptor':
35065 <<<<<<< HEAD
35066                         case 'cancellable':
35067 =======
35068                           break;
35069                         case 'timeout':
35070                           httpConfig[key] = value;
35071 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35072                           break;
35073                       }
35074                     });
35075
35076 <<<<<<< HEAD
35077                     if (!isInstanceCall && cancellable) {
35078                       timeoutDeferred = $q.defer();
35079                       httpConfig.timeout = timeoutDeferred.promise;
35080
35081                       if (numericTimeout) {
35082                         numericTimeoutPromise = $timeout(timeoutDeferred.resolve, numericTimeout);
35083                       }
35084                     }
35085
35086 =======
35087 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35088                     if (hasBody) httpConfig.data = data;
35089                     route.setUrlParams(httpConfig,
35090                       extend({}, extractParams(data, action.params || {}), params),
35091                       action.url);
35092
35093                     var promise = $http(httpConfig).then(function(response) {
35094 <<<<<<< HEAD
35095                       var data = response.data;
35096
35097                       if (data) {
35098                         // Need to convert action.isArray to boolean in case it is undefined
35099                         if (isArray(data) !== (!!action.isArray)) {
35100                           throw $resourceMinErr('badcfg',
35101                               'Error in resource configuration for action `{0}`. Expected response to ' +
35102                               'contain an {1} but got an {2} (Request: {3} {4})', name, action.isArray ? 'array' : 'object',
35103                             isArray(data) ? 'array' : 'object', httpConfig.method, httpConfig.url);
35104                         }
35105                         if (action.isArray) {
35106                           value.length = 0;
35107                           forEach(data, function(item) {
35108                             if (typeof item === 'object') {
35109 =======
35110                       var data = response.data,
35111                         promise = value.$promise;
35112
35113                       if (data) {
35114                         // Need to convert action.isArray to boolean in case it is undefined
35115                         // jshint -W018
35116                         if (angular.isArray(data) !== (!!action.isArray)) {
35117                           throw $resourceMinErr('badcfg',
35118                               'Error in resource configuration for action `{0}`. Expected response to ' +
35119                               'contain an {1} but got an {2} (Request: {3} {4})', name, action.isArray ? 'array' : 'object',
35120                             angular.isArray(data) ? 'array' : 'object', httpConfig.method, httpConfig.url);
35121                         }
35122                         // jshint +W018
35123                         if (action.isArray) {
35124                           value.length = 0;
35125                           forEach(data, function(item) {
35126                             if (typeof item === "object") {
35127 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35128                               value.push(new Resource(item));
35129                             } else {
35130                               // Valid JSON values may be string literals, and these should not be converted
35131                               // into objects. These items will not have access to the Resource prototype
35132                               // methods, but unfortunately there
35133                               value.push(item);
35134                             }
35135                           });
35136                         } else {
35137 <<<<<<< HEAD
35138                           var promise = value.$promise;     // Save the promise
35139                           shallowClearAndCopy(data, value);
35140                           value.$promise = promise;         // Restore the promise
35141                         }
35142                       }
35143                       response.resource = value;
35144
35145                       return response;
35146                     });
35147
35148                     promise = promise['finally'](function() {
35149                       value.$resolved = true;
35150                       if (!isInstanceCall && cancellable) {
35151                         value.$cancelRequest = noop;
35152                         $timeout.cancel(numericTimeoutPromise);
35153                         timeoutDeferred = numericTimeoutPromise = httpConfig.timeout = null;
35154                       }
35155 =======
35156                           shallowClearAndCopy(data, value);
35157                           value.$promise = promise;
35158                         }
35159                       }
35160
35161                       value.$resolved = true;
35162
35163                       response.resource = value;
35164
35165                       return response;
35166                     }, function(response) {
35167                       value.$resolved = true;
35168
35169                       (error || noop)(response);
35170
35171                       return $q.reject(response);
35172 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35173                     });
35174
35175                     promise = promise.then(
35176                       function(response) {
35177                         var value = responseInterceptor(response);
35178 <<<<<<< HEAD
35179                         (success || noop)(value, response.headers, response.status, response.statusText);
35180                         return value;
35181                       },
35182                       (hasError || hasResponseErrorInterceptor) ?
35183                         function(response) {
35184                           if (hasError && !hasResponseErrorInterceptor) {
35185                             // Avoid `Possibly Unhandled Rejection` error,
35186                             // but still fulfill the returned promise with a rejection
35187                             promise.catch(noop);
35188                           }
35189                           if (hasError) error(response);
35190                           return hasResponseErrorInterceptor ?
35191                             responseErrorInterceptor(response) :
35192                             $q.reject(response);
35193                         } :
35194                         undefined);
35195 =======
35196                         (success || noop)(value, response.headers);
35197                         return value;
35198                       },
35199                       responseErrorInterceptor);
35200 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35201
35202                     if (!isInstanceCall) {
35203                       // we are creating instance / collection
35204                       // - set the initial promise
35205                       // - return the instance / collection
35206                       value.$promise = promise;
35207                       value.$resolved = false;
35208 <<<<<<< HEAD
35209                       if (cancellable) value.$cancelRequest = cancelRequest;
35210 =======
35211 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35212
35213                       return value;
35214                     }
35215
35216                     // instance call
35217                     return promise;
35218 <<<<<<< HEAD
35219
35220                     function cancelRequest(value) {
35221                       promise.catch(noop);
35222                       timeoutDeferred.resolve(value);
35223                     }
35224 =======
35225 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35226                   };
35227
35228
35229                   Resource.prototype['$' + name] = function(params, success, error) {
35230                     if (isFunction(params)) {
35231                       error = success; success = params; params = {};
35232                     }
35233                     var result = Resource[name].call(this, params, this, success, error);
35234                     return result.$promise || result;
35235                   };
35236                 });
35237
35238                 Resource.bind = function(additionalParamDefaults) {
35239 <<<<<<< HEAD
35240                   var extendedParamDefaults = extend({}, paramDefaults, additionalParamDefaults);
35241                   return resourceFactory(url, extendedParamDefaults, actions, options);
35242 =======
35243                   return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
35244 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35245                 };
35246
35247                 return Resource;
35248               }
35249
35250               return resourceFactory;
35251             }];
35252           });
35253
35254
35255         })(window, window.angular);
35256
35257
35258 /***/ },
35259 /* 6 */
35260 /***/ function(module, exports, __webpack_require__) {
35261
35262         __webpack_require__(7);
35263
35264         module.exports = 'ui.bootstrap';
35265
35266
35267 /***/ },
35268 /* 7 */
35269 /***/ function(module, exports) {
35270
35271         /*
35272          * angular-ui-bootstrap
35273          * http://angular-ui.github.io/bootstrap/
35274
35275 <<<<<<< HEAD
35276          * Version: 1.3.3 - 2016-05-22
35277          * License: MIT
35278          */angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
35279         angular.module("ui.bootstrap.tpls", ["uib/template/accordion/accordion-group.html","uib/template/accordion/accordion.html","uib/template/alert/alert.html","uib/template/carousel/carousel.html","uib/template/carousel/slide.html","uib/template/datepicker/datepicker.html","uib/template/datepicker/day.html","uib/template/datepicker/month.html","uib/template/datepicker/year.html","uib/template/datepickerPopup/popup.html","uib/template/modal/backdrop.html","uib/template/modal/window.html","uib/template/pager/pager.html","uib/template/pagination/pagination.html","uib/template/tooltip/tooltip-html-popup.html","uib/template/tooltip/tooltip-popup.html","uib/template/tooltip/tooltip-template-popup.html","uib/template/popover/popover-html.html","uib/template/popover/popover-template.html","uib/template/popover/popover.html","uib/template/progressbar/bar.html","uib/template/progressbar/progress.html","uib/template/progressbar/progressbar.html","uib/template/rating/rating.html","uib/template/tabs/tab.html","uib/template/tabs/tabset.html","uib/template/timepicker/timepicker.html","uib/template/typeahead/typeahead-match.html","uib/template/typeahead/typeahead-popup.html"]);
35280         angular.module('ui.bootstrap.collapse', [])
35281
35282           .directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function($animate, $q, $parse, $injector) {
35283             var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;
35284             return {
35285               link: function(scope, element, attrs) {
35286                 var expandingExpr = $parse(attrs.expanding),
35287                     expandedExpr = $parse(attrs.expanded),
35288                     collapsingExpr = $parse(attrs.collapsing),
35289                     collapsedExpr = $parse(attrs.collapsed);
35290
35291                 if (!scope.$eval(attrs.uibCollapse)) {
35292                   element.addClass('in')
35293                     .addClass('collapse')
35294                     .attr('aria-expanded', true)
35295                     .attr('aria-hidden', false)
35296 =======
35297          * Version: 1.0.0 - 2016-01-08
35298          * License: MIT
35299          */
35300         angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.debounce","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
35301         angular.module("ui.bootstrap.tpls", ["uib/template/accordion/accordion-group.html","uib/template/accordion/accordion.html","uib/template/alert/alert.html","uib/template/carousel/carousel.html","uib/template/carousel/slide.html","uib/template/datepicker/datepicker.html","uib/template/datepicker/day.html","uib/template/datepicker/month.html","uib/template/datepicker/popup.html","uib/template/datepicker/year.html","uib/template/modal/backdrop.html","uib/template/modal/window.html","uib/template/pager/pager.html","uib/template/pagination/pagination.html","uib/template/tooltip/tooltip-html-popup.html","uib/template/tooltip/tooltip-popup.html","uib/template/tooltip/tooltip-template-popup.html","uib/template/popover/popover-html.html","uib/template/popover/popover-template.html","uib/template/popover/popover.html","uib/template/progressbar/bar.html","uib/template/progressbar/progress.html","uib/template/progressbar/progressbar.html","uib/template/rating/rating.html","uib/template/tabs/tab.html","uib/template/tabs/tabset.html","uib/template/timepicker/timepicker.html","uib/template/typeahead/typeahead-match.html","uib/template/typeahead/typeahead-popup.html"]);
35302         angular.module('ui.bootstrap.collapse', [])
35303
35304           .directive('uibCollapse', ['$animate', '$injector', function($animate, $injector) {
35305             var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;
35306             return {
35307               link: function(scope, element, attrs) {
35308                 if (!scope.$eval(attrs.uibCollapse)) {
35309                   element.addClass('in')
35310                     .addClass('collapse')
35311 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35312                     .css({height: 'auto'});
35313                 }
35314
35315                 function expand() {
35316 <<<<<<< HEAD
35317                   if (element.hasClass('collapse') && element.hasClass('in')) {
35318                     return;
35319                   }
35320
35321                   $q.resolve(expandingExpr(scope))
35322                     .then(function() {
35323                       element.removeClass('collapse')
35324                         .addClass('collapsing')
35325                         .attr('aria-expanded', true)
35326                         .attr('aria-hidden', false);
35327
35328                       if ($animateCss) {
35329                         $animateCss(element, {
35330                           addClass: 'in',
35331                           easing: 'ease',
35332                           to: { height: element[0].scrollHeight + 'px' }
35333                         }).start()['finally'](expandDone);
35334                       } else {
35335                         $animate.addClass(element, 'in', {
35336                           to: { height: element[0].scrollHeight + 'px' }
35337                         }).then(expandDone);
35338                       }
35339                     });
35340 =======
35341                   element.removeClass('collapse')
35342                     .addClass('collapsing')
35343                     .attr('aria-expanded', true)
35344                     .attr('aria-hidden', false);
35345
35346                   if ($animateCss) {
35347                     $animateCss(element, {
35348                       addClass: 'in',
35349                       easing: 'ease',
35350                       to: { height: element[0].scrollHeight + 'px' }
35351                     }).start()['finally'](expandDone);
35352                   } else {
35353                     $animate.addClass(element, 'in', {
35354                       to: { height: element[0].scrollHeight + 'px' }
35355                     }).then(expandDone);
35356                   }
35357 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35358                 }
35359
35360                 function expandDone() {
35361                   element.removeClass('collapsing')
35362                     .addClass('collapse')
35363                     .css({height: 'auto'});
35364 <<<<<<< HEAD
35365                   expandedExpr(scope);
35366 =======
35367 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35368                 }
35369
35370                 function collapse() {
35371                   if (!element.hasClass('collapse') && !element.hasClass('in')) {
35372                     return collapseDone();
35373                   }
35374
35375 <<<<<<< HEAD
35376                   $q.resolve(collapsingExpr(scope))
35377                     .then(function() {
35378                       element
35379                         // IMPORTANT: The height must be set before adding "collapsing" class.
35380                         // Otherwise, the browser attempts to animate from height 0 (in
35381                         // collapsing class) to the given height here.
35382                         .css({height: element[0].scrollHeight + 'px'})
35383                         // initially all panel collapse have the collapse class, this removal
35384                         // prevents the animation from jumping to collapsed state
35385                         .removeClass('collapse')
35386                         .addClass('collapsing')
35387                         .attr('aria-expanded', false)
35388                         .attr('aria-hidden', true);
35389
35390                       if ($animateCss) {
35391                         $animateCss(element, {
35392                           removeClass: 'in',
35393                           to: {height: '0'}
35394                         }).start()['finally'](collapseDone);
35395                       } else {
35396                         $animate.removeClass(element, 'in', {
35397                           to: {height: '0'}
35398                         }).then(collapseDone);
35399                       }
35400                     });
35401 =======
35402                   element
35403                     // IMPORTANT: The height must be set before adding "collapsing" class.
35404                     // Otherwise, the browser attempts to animate from height 0 (in
35405                     // collapsing class) to the given height here.
35406                     .css({height: element[0].scrollHeight + 'px'})
35407                     // initially all panel collapse have the collapse class, this removal
35408                     // prevents the animation from jumping to collapsed state
35409                     .removeClass('collapse')
35410                     .addClass('collapsing')
35411                     .attr('aria-expanded', false)
35412                     .attr('aria-hidden', true);
35413
35414                   if ($animateCss) {
35415                     $animateCss(element, {
35416                       removeClass: 'in',
35417                       to: {height: '0'}
35418                     }).start()['finally'](collapseDone);
35419                   } else {
35420                     $animate.removeClass(element, 'in', {
35421                       to: {height: '0'}
35422                     }).then(collapseDone);
35423                   }
35424 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35425                 }
35426
35427                 function collapseDone() {
35428                   element.css({height: '0'}); // Required so that collapse works when animation is disabled
35429                   element.removeClass('collapsing')
35430                     .addClass('collapse');
35431 <<<<<<< HEAD
35432                   collapsedExpr(scope);
35433 =======
35434 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35435                 }
35436
35437                 scope.$watch(attrs.uibCollapse, function(shouldCollapse) {
35438                   if (shouldCollapse) {
35439                     collapse();
35440                   } else {
35441                     expand();
35442                   }
35443                 });
35444               }
35445             };
35446           }]);
35447
35448         angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
35449
35450         .constant('uibAccordionConfig', {
35451           closeOthers: true
35452         })
35453
35454         .controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function($scope, $attrs, accordionConfig) {
35455           // This array keeps track of the accordion groups
35456           this.groups = [];
35457
35458           // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
35459           this.closeOthers = function(openGroup) {
35460             var closeOthers = angular.isDefined($attrs.closeOthers) ?
35461               $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
35462             if (closeOthers) {
35463               angular.forEach(this.groups, function(group) {
35464                 if (group !== openGroup) {
35465                   group.isOpen = false;
35466                 }
35467               });
35468             }
35469           };
35470
35471           // This is called from the accordion-group directive to add itself to the accordion
35472           this.addGroup = function(groupScope) {
35473             var that = this;
35474             this.groups.push(groupScope);
35475
35476             groupScope.$on('$destroy', function(event) {
35477               that.removeGroup(groupScope);
35478             });
35479           };
35480
35481           // This is called from the accordion-group directive when to remove itself
35482           this.removeGroup = function(group) {
35483             var index = this.groups.indexOf(group);
35484             if (index !== -1) {
35485               this.groups.splice(index, 1);
35486             }
35487           };
35488         }])
35489
35490         // The accordion directive simply sets up the directive controller
35491         // and adds an accordion CSS class to itself element.
35492         .directive('uibAccordion', function() {
35493           return {
35494             controller: 'UibAccordionController',
35495             controllerAs: 'accordion',
35496             transclude: true,
35497             templateUrl: function(element, attrs) {
35498               return attrs.templateUrl || 'uib/template/accordion/accordion.html';
35499             }
35500           };
35501         })
35502
35503         // The accordion-group directive indicates a block of html that will expand and collapse in an accordion
35504         .directive('uibAccordionGroup', function() {
35505           return {
35506             require: '^uibAccordion',         // We need this directive to be inside an accordion
35507             transclude: true,              // It transcludes the contents of the directive into the template
35508             replace: true,                // The element containing the directive will be replaced with the template
35509             templateUrl: function(element, attrs) {
35510               return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
35511             },
35512             scope: {
35513               heading: '@',               // Interpolate the heading attribute onto this scope
35514 <<<<<<< HEAD
35515               panelClass: '@?',           // Ditto with panelClass
35516 =======
35517 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35518               isOpen: '=?',
35519               isDisabled: '=?'
35520             },
35521             controller: function() {
35522               this.setHeading = function(element) {
35523                 this.heading = element;
35524               };
35525             },
35526             link: function(scope, element, attrs, accordionCtrl) {
35527               accordionCtrl.addGroup(scope);
35528
35529               scope.openClass = attrs.openClass || 'panel-open';
35530               scope.panelClass = attrs.panelClass || 'panel-default';
35531               scope.$watch('isOpen', function(value) {
35532                 element.toggleClass(scope.openClass, !!value);
35533                 if (value) {
35534                   accordionCtrl.closeOthers(scope);
35535                 }
35536               });
35537
35538               scope.toggleOpen = function($event) {
35539                 if (!scope.isDisabled) {
35540                   if (!$event || $event.which === 32) {
35541                     scope.isOpen = !scope.isOpen;
35542                   }
35543                 }
35544               };
35545 <<<<<<< HEAD
35546
35547               var id = 'accordiongroup-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
35548               scope.headingId = id + '-tab';
35549               scope.panelId = id + '-panel';
35550 =======
35551 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35552             }
35553           };
35554         })
35555
35556         // Use accordion-heading below an accordion-group to provide a heading containing HTML
35557         .directive('uibAccordionHeading', function() {
35558           return {
35559             transclude: true,   // Grab the contents to be used as the heading
35560             template: '',       // In effect remove this element!
35561             replace: true,
35562             require: '^uibAccordionGroup',
35563             link: function(scope, element, attrs, accordionGroupCtrl, transclude) {
35564               // Pass the heading to the accordion-group controller
35565               // so that it can be transcluded into the right place in the template
35566               // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
35567               accordionGroupCtrl.setHeading(transclude(scope, angular.noop));
35568             }
35569           };
35570         })
35571
35572         // Use in the accordion-group template to indicate where you want the heading to be transcluded
35573         // You must provide the property on the accordion-group controller that will hold the transcluded element
35574         .directive('uibAccordionTransclude', function() {
35575           return {
35576             require: '^uibAccordionGroup',
35577             link: function(scope, element, attrs, controller) {
35578               scope.$watch(function() { return controller[attrs.uibAccordionTransclude]; }, function(heading) {
35579                 if (heading) {
35580 <<<<<<< HEAD
35581                   var elem = angular.element(element[0].querySelector(getHeaderSelectors()));
35582                   elem.html('');
35583                   elem.append(heading);
35584 =======
35585                   element.find('span').html('');
35586                   element.find('span').append(heading);
35587 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35588                 }
35589               });
35590             }
35591           };
35592 <<<<<<< HEAD
35593
35594           function getHeaderSelectors() {
35595               return 'uib-accordion-header,' +
35596                   'data-uib-accordion-header,' +
35597                   'x-uib-accordion-header,' +
35598                   'uib\\:accordion-header,' +
35599                   '[uib-accordion-header],' +
35600                   '[data-uib-accordion-header],' +
35601                   '[x-uib-accordion-header]';
35602           }
35603 =======
35604 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35605         });
35606
35607         angular.module('ui.bootstrap.alert', [])
35608
35609         .controller('UibAlertController', ['$scope', '$attrs', '$interpolate', '$timeout', function($scope, $attrs, $interpolate, $timeout) {
35610           $scope.closeable = !!$attrs.close;
35611
35612           var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?
35613             $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;
35614
35615           if (dismissOnTimeout) {
35616             $timeout(function() {
35617               $scope.close();
35618             }, parseInt(dismissOnTimeout, 10));
35619           }
35620         }])
35621
35622         .directive('uibAlert', function() {
35623           return {
35624             controller: 'UibAlertController',
35625             controllerAs: 'alert',
35626             templateUrl: function(element, attrs) {
35627               return attrs.templateUrl || 'uib/template/alert/alert.html';
35628             },
35629             transclude: true,
35630             replace: true,
35631             scope: {
35632               type: '@',
35633               close: '&'
35634             }
35635           };
35636         });
35637
35638         angular.module('ui.bootstrap.buttons', [])
35639
35640         .constant('uibButtonConfig', {
35641           activeClass: 'active',
35642           toggleEvent: 'click'
35643         })
35644
35645         .controller('UibButtonsController', ['uibButtonConfig', function(buttonConfig) {
35646           this.activeClass = buttonConfig.activeClass || 'active';
35647           this.toggleEvent = buttonConfig.toggleEvent || 'click';
35648         }])
35649
35650         .directive('uibBtnRadio', ['$parse', function($parse) {
35651           return {
35652             require: ['uibBtnRadio', 'ngModel'],
35653             controller: 'UibButtonsController',
35654             controllerAs: 'buttons',
35655             link: function(scope, element, attrs, ctrls) {
35656               var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
35657               var uncheckableExpr = $parse(attrs.uibUncheckable);
35658
35659               element.find('input').css({display: 'none'});
35660
35661               //model -> UI
35662               ngModelCtrl.$render = function() {
35663                 element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));
35664               };
35665
35666               //ui->model
35667               element.on(buttonsCtrl.toggleEvent, function() {
35668                 if (attrs.disabled) {
35669                   return;
35670                 }
35671
35672                 var isActive = element.hasClass(buttonsCtrl.activeClass);
35673
35674                 if (!isActive || angular.isDefined(attrs.uncheckable)) {
35675                   scope.$apply(function() {
35676                     ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));
35677                     ngModelCtrl.$render();
35678                   });
35679                 }
35680               });
35681
35682               if (attrs.uibUncheckable) {
35683                 scope.$watch(uncheckableExpr, function(uncheckable) {
35684 <<<<<<< HEAD
35685                   attrs.$set('uncheckable', uncheckable ? '' : undefined);
35686 =======
35687                   attrs.$set('uncheckable', uncheckable ? '' : null);
35688 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35689                 });
35690               }
35691             }
35692           };
35693         }])
35694
35695         .directive('uibBtnCheckbox', function() {
35696           return {
35697             require: ['uibBtnCheckbox', 'ngModel'],
35698             controller: 'UibButtonsController',
35699             controllerAs: 'button',
35700             link: function(scope, element, attrs, ctrls) {
35701               var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
35702
35703               element.find('input').css({display: 'none'});
35704
35705               function getTrueValue() {
35706                 return getCheckboxValue(attrs.btnCheckboxTrue, true);
35707               }
35708
35709               function getFalseValue() {
35710                 return getCheckboxValue(attrs.btnCheckboxFalse, false);
35711               }
35712
35713               function getCheckboxValue(attribute, defaultValue) {
35714                 return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;
35715               }
35716
35717               //model -> UI
35718               ngModelCtrl.$render = function() {
35719                 element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
35720               };
35721
35722               //ui->model
35723               element.on(buttonsCtrl.toggleEvent, function() {
35724                 if (attrs.disabled) {
35725                   return;
35726                 }
35727
35728                 scope.$apply(function() {
35729                   ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
35730                   ngModelCtrl.$render();
35731                 });
35732               });
35733             }
35734           };
35735         });
35736
35737         angular.module('ui.bootstrap.carousel', [])
35738
35739         .controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function($scope, $element, $interval, $timeout, $animate) {
35740           var self = this,
35741             slides = self.slides = $scope.slides = [],
35742             SLIDE_DIRECTION = 'uib-slideDirection',
35743 <<<<<<< HEAD
35744             currentIndex = $scope.active,
35745             currentInterval, isPlaying, bufferedTransitions = [];
35746 =======
35747             currentIndex = -1,
35748             currentInterval, isPlaying, bufferedTransitions = [];
35749           self.currentSlide = null;
35750 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35751
35752           var destroyed = false;
35753
35754           self.addSlide = function(slide, element) {
35755 <<<<<<< HEAD
35756             slides.push({
35757               slide: slide,
35758               element: element
35759             });
35760             slides.sort(function(a, b) {
35761               return +a.slide.index - +b.slide.index;
35762             });
35763             //if this is the first slide or the slide is set to active, select it
35764             if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) {
35765 =======
35766             slide.$element = element;
35767             slides.push(slide);
35768             //if this is the first slide or the slide is set to active, select it
35769             if (slides.length === 1 || slide.active) {
35770 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35771               if ($scope.$currentTransition) {
35772                 $scope.$currentTransition = null;
35773               }
35774
35775 <<<<<<< HEAD
35776               currentIndex = slide.index;
35777               $scope.active = slide.index;
35778               setActive(currentIndex);
35779               self.select(slides[findSlideIndex(slide)]);
35780               if (slides.length === 1) {
35781                 $scope.play();
35782               }
35783 =======
35784               self.select(slides[slides.length - 1]);
35785               if (slides.length === 1) {
35786                 $scope.play();
35787               }
35788             } else {
35789               slide.active = false;
35790 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35791             }
35792           };
35793
35794           self.getCurrentIndex = function() {
35795 <<<<<<< HEAD
35796             for (var i = 0; i < slides.length; i++) {
35797               if (slides[i].slide.index === currentIndex) {
35798                 return i;
35799               }
35800             }
35801 =======
35802             if (self.currentSlide && angular.isDefined(self.currentSlide.index)) {
35803               return +self.currentSlide.index;
35804             }
35805             return currentIndex;
35806 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35807           };
35808
35809           self.next = $scope.next = function() {
35810             var newIndex = (self.getCurrentIndex() + 1) % slides.length;
35811
35812             if (newIndex === 0 && $scope.noWrap()) {
35813               $scope.pause();
35814               return;
35815             }
35816
35817 <<<<<<< HEAD
35818             return self.select(slides[newIndex], 'next');
35819 =======
35820             return self.select(getSlideByIndex(newIndex), 'next');
35821 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35822           };
35823
35824           self.prev = $scope.prev = function() {
35825             var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;
35826
35827             if ($scope.noWrap() && newIndex === slides.length - 1) {
35828               $scope.pause();
35829               return;
35830             }
35831
35832 <<<<<<< HEAD
35833             return self.select(slides[newIndex], 'prev');
35834           };
35835
35836           self.removeSlide = function(slide) {
35837             var index = findSlideIndex(slide);
35838
35839             var bufferedIndex = bufferedTransitions.indexOf(slides[index]);
35840             if (bufferedIndex !== -1) {
35841               bufferedTransitions.splice(bufferedIndex, 1);
35842             }
35843
35844             //get the index of the slide inside the carousel
35845             slides.splice(index, 1);
35846             if (slides.length > 0 && currentIndex === index) {
35847               if (index >= slides.length) {
35848                 currentIndex = slides.length - 1;
35849                 $scope.active = currentIndex;
35850                 setActive(currentIndex);
35851                 self.select(slides[slides.length - 1]);
35852               } else {
35853                 currentIndex = index;
35854                 $scope.active = currentIndex;
35855                 setActive(currentIndex);
35856                 self.select(slides[index]);
35857               }
35858             } else if (currentIndex > index) {
35859               currentIndex--;
35860               $scope.active = currentIndex;
35861             }
35862
35863             //clean the active value when no more slide
35864             if (slides.length === 0) {
35865               currentIndex = null;
35866               $scope.active = null;
35867 =======
35868             return self.select(getSlideByIndex(newIndex), 'prev');
35869           };
35870
35871           self.removeSlide = function(slide) {
35872             if (angular.isDefined(slide.index)) {
35873               slides.sort(function(a, b) {
35874                 return +a.index > +b.index;
35875               });
35876             }
35877
35878             var bufferedIndex = bufferedTransitions.indexOf(slide);
35879             if (bufferedIndex !== -1) {
35880               bufferedTransitions.splice(bufferedIndex, 1);
35881             }
35882             //get the index of the slide inside the carousel
35883             var index = slides.indexOf(slide);
35884             slides.splice(index, 1);
35885             $timeout(function() {
35886               if (slides.length > 0 && slide.active) {
35887                 if (index >= slides.length) {
35888                   self.select(slides[index - 1]);
35889                 } else {
35890                   self.select(slides[index]);
35891                 }
35892               } else if (currentIndex > index) {
35893                 currentIndex--;
35894               }
35895             });
35896
35897             //clean the currentSlide when no more slide
35898             if (slides.length === 0) {
35899               self.currentSlide = null;
35900 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35901               clearBufferedTransitions();
35902             }
35903           };
35904
35905           /* direction: "prev" or "next" */
35906           self.select = $scope.select = function(nextSlide, direction) {
35907 <<<<<<< HEAD
35908             var nextIndex = findSlideIndex(nextSlide.slide);
35909 =======
35910             var nextIndex = $scope.indexOfSlide(nextSlide);
35911 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35912             //Decide direction if it's not given
35913             if (direction === undefined) {
35914               direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
35915             }
35916             //Prevent this user-triggered transition from occurring if there is already one in progress
35917 <<<<<<< HEAD
35918             if (nextSlide.slide.index !== currentIndex &&
35919               !$scope.$currentTransition) {
35920               goNext(nextSlide.slide, nextIndex, direction);
35921             } else if (nextSlide && nextSlide.slide.index !== currentIndex && $scope.$currentTransition) {
35922               bufferedTransitions.push(slides[nextIndex]);
35923 =======
35924             if (nextSlide && nextSlide !== self.currentSlide && !$scope.$currentTransition) {
35925               goNext(nextSlide, nextIndex, direction);
35926             } else if (nextSlide && nextSlide !== self.currentSlide && $scope.$currentTransition) {
35927               bufferedTransitions.push(nextSlide);
35928 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35929             }
35930           };
35931
35932           /* Allow outside people to call indexOf on slides array */
35933           $scope.indexOfSlide = function(slide) {
35934 <<<<<<< HEAD
35935             return +slide.slide.index;
35936           };
35937
35938           $scope.isActive = function(slide) {
35939             return $scope.active === slide.slide.index;
35940           };
35941
35942           $scope.isPrevDisabled = function() {
35943             return $scope.active === 0 && $scope.noWrap();
35944           };
35945
35946           $scope.isNextDisabled = function() {
35947             return $scope.active === slides.length - 1 && $scope.noWrap();
35948 =======
35949             return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide);
35950           };
35951
35952           $scope.isActive = function(slide) {
35953             return self.currentSlide === slide;
35954 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
35955           };
35956
35957           $scope.pause = function() {
35958             if (!$scope.noPause) {
35959               isPlaying = false;
35960               resetTimer();
35961             }
35962           };
35963
35964           $scope.play = function() {
35965             if (!isPlaying) {
35966               isPlaying = true;
35967               restartTimer();
35968             }
35969           };
35970
35971           $scope.$on('$destroy', function() {
35972             destroyed = true;
35973             resetTimer();
35974           });
35975
35976           $scope.$watch('noTransition', function(noTransition) {
35977             $animate.enabled($element, !noTransition);
35978           });
35979
35980           $scope.$watch('interval', restartTimer);
35981
35982           $scope.$watchCollection('slides', resetTransition);
35983
35984 <<<<<<< HEAD
35985           $scope.$watch('active', function(index) {
35986             if (angular.isNumber(index) && currentIndex !== index) {
35987               for (var i = 0; i < slides.length; i++) {
35988                 if (slides[i].slide.index === index) {
35989                   index = i;
35990                   break;
35991                 }
35992               }
35993
35994               var slide = slides[index];
35995               if (slide) {
35996                 setActive(index);
35997                 self.select(slides[index]);
35998                 currentIndex = index;
35999               }
36000             }
36001           });
36002
36003 =======
36004 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36005           function clearBufferedTransitions() {
36006             while (bufferedTransitions.length) {
36007               bufferedTransitions.shift();
36008             }
36009           }
36010
36011           function getSlideByIndex(index) {
36012 <<<<<<< HEAD
36013 =======
36014             if (angular.isUndefined(slides[index].index)) {
36015               return slides[index];
36016             }
36017 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36018             for (var i = 0, l = slides.length; i < l; ++i) {
36019               if (slides[i].index === index) {
36020                 return slides[i];
36021               }
36022             }
36023           }
36024
36025 <<<<<<< HEAD
36026           function setActive(index) {
36027             for (var i = 0; i < slides.length; i++) {
36028               slides[i].slide.active = i === index;
36029             }
36030           }
36031
36032           function goNext(slide, index, direction) {
36033             if (destroyed) {
36034               return;
36035             }
36036
36037             angular.extend(slide, {direction: direction});
36038             angular.extend(slides[currentIndex].slide || {}, {direction: direction});
36039             if ($animate.enabled($element) && !$scope.$currentTransition &&
36040               slides[index].element && self.slides.length > 1) {
36041               slides[index].element.data(SLIDE_DIRECTION, slide.direction);
36042               var currentIdx = self.getCurrentIndex();
36043
36044               if (angular.isNumber(currentIdx) && slides[currentIdx].element) {
36045                 slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction);
36046               }
36047
36048               $scope.$currentTransition = true;
36049               $animate.on('addClass', slides[index].element, function(element, phase) {
36050 =======
36051           function goNext(slide, index, direction) {
36052             if (destroyed) { return; }
36053
36054             angular.extend(slide, {direction: direction, active: true});
36055             angular.extend(self.currentSlide || {}, {direction: direction, active: false});
36056             if ($animate.enabled($element) && !$scope.$currentTransition &&
36057               slide.$element && self.slides.length > 1) {
36058               slide.$element.data(SLIDE_DIRECTION, slide.direction);
36059               if (self.currentSlide && self.currentSlide.$element) {
36060                 self.currentSlide.$element.data(SLIDE_DIRECTION, slide.direction);
36061               }
36062
36063               $scope.$currentTransition = true;
36064               $animate.on('addClass', slide.$element, function(element, phase) {
36065 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36066                 if (phase === 'close') {
36067                   $scope.$currentTransition = null;
36068                   $animate.off('addClass', element);
36069                   if (bufferedTransitions.length) {
36070 <<<<<<< HEAD
36071                     var nextSlide = bufferedTransitions.pop().slide;
36072                     var nextIndex = nextSlide.index;
36073 =======
36074                     var nextSlide = bufferedTransitions.pop();
36075                     var nextIndex = $scope.indexOfSlide(nextSlide);
36076 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36077                     var nextDirection = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
36078                     clearBufferedTransitions();
36079
36080                     goNext(nextSlide, nextIndex, nextDirection);
36081                   }
36082                 }
36083               });
36084             }
36085
36086 <<<<<<< HEAD
36087             $scope.active = slide.index;
36088             currentIndex = slide.index;
36089             setActive(index);
36090 =======
36091             self.currentSlide = slide;
36092             currentIndex = index;
36093 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36094
36095             //every time you change slides, reset the timer
36096             restartTimer();
36097           }
36098
36099 <<<<<<< HEAD
36100           function findSlideIndex(slide) {
36101             for (var i = 0; i < slides.length; i++) {
36102               if (slides[i].slide === slide) {
36103                 return i;
36104               }
36105             }
36106           }
36107
36108 =======
36109 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36110           function resetTimer() {
36111             if (currentInterval) {
36112               $interval.cancel(currentInterval);
36113               currentInterval = null;
36114             }
36115           }
36116
36117           function resetTransition(slides) {
36118             if (!slides.length) {
36119               $scope.$currentTransition = null;
36120               clearBufferedTransitions();
36121             }
36122           }
36123
36124           function restartTimer() {
36125             resetTimer();
36126             var interval = +$scope.interval;
36127             if (!isNaN(interval) && interval > 0) {
36128               currentInterval = $interval(timerFn, interval);
36129             }
36130           }
36131
36132           function timerFn() {
36133             var interval = +$scope.interval;
36134             if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
36135               $scope.next();
36136             } else {
36137               $scope.pause();
36138             }
36139           }
36140         }])
36141
36142         .directive('uibCarousel', function() {
36143           return {
36144             transclude: true,
36145             replace: true,
36146             controller: 'UibCarouselController',
36147             controllerAs: 'carousel',
36148             templateUrl: function(element, attrs) {
36149               return attrs.templateUrl || 'uib/template/carousel/carousel.html';
36150             },
36151             scope: {
36152 <<<<<<< HEAD
36153               active: '=',
36154 =======
36155 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36156               interval: '=',
36157               noTransition: '=',
36158               noPause: '=',
36159               noWrap: '&'
36160             }
36161           };
36162         })
36163
36164         .directive('uibSlide', function() {
36165           return {
36166             require: '^uibCarousel',
36167             transclude: true,
36168             replace: true,
36169             templateUrl: function(element, attrs) {
36170               return attrs.templateUrl || 'uib/template/carousel/slide.html';
36171             },
36172             scope: {
36173 <<<<<<< HEAD
36174 =======
36175               active: '=?',
36176 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36177               actual: '=?',
36178               index: '=?'
36179             },
36180             link: function (scope, element, attrs, carouselCtrl) {
36181               carouselCtrl.addSlide(scope, element);
36182               //when the scope is destroyed then remove the slide from the current slides array
36183               scope.$on('$destroy', function() {
36184                 carouselCtrl.removeSlide(scope);
36185               });
36186 <<<<<<< HEAD
36187 =======
36188
36189               scope.$watch('active', function(active) {
36190                 if (active) {
36191                   carouselCtrl.select(scope);
36192                 }
36193               });
36194 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36195             }
36196           };
36197         })
36198
36199         .animation('.item', ['$animateCss',
36200         function($animateCss) {
36201           var SLIDE_DIRECTION = 'uib-slideDirection';
36202
36203           function removeClass(element, className, callback) {
36204             element.removeClass(className);
36205             if (callback) {
36206               callback();
36207             }
36208           }
36209
36210           return {
36211             beforeAddClass: function(element, className, done) {
36212               if (className === 'active') {
36213                 var stopped = false;
36214                 var direction = element.data(SLIDE_DIRECTION);
36215                 var directionClass = direction === 'next' ? 'left' : 'right';
36216                 var removeClassFn = removeClass.bind(this, element,
36217                   directionClass + ' ' + direction, done);
36218                 element.addClass(direction);
36219
36220                 $animateCss(element, {addClass: directionClass})
36221                   .start()
36222                   .done(removeClassFn);
36223
36224                 return function() {
36225                   stopped = true;
36226                 };
36227               }
36228               done();
36229             },
36230             beforeRemoveClass: function (element, className, done) {
36231               if (className === 'active') {
36232                 var stopped = false;
36233                 var direction = element.data(SLIDE_DIRECTION);
36234                 var directionClass = direction === 'next' ? 'left' : 'right';
36235                 var removeClassFn = removeClass.bind(this, element, directionClass, done);
36236
36237                 $animateCss(element, {addClass: directionClass})
36238                   .start()
36239                   .done(removeClassFn);
36240
36241                 return function() {
36242                   stopped = true;
36243                 };
36244               }
36245               done();
36246             }
36247           };
36248         }]);
36249
36250         angular.module('ui.bootstrap.dateparser', [])
36251
36252 <<<<<<< HEAD
36253         .service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', function($log, $locale, dateFilter, orderByFilter) {
36254 =======
36255         .service('uibDateParser', ['$log', '$locale', 'orderByFilter', function($log, $locale, orderByFilter) {
36256 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36257           // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js
36258           var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
36259
36260           var localeId;
36261           var formatCodeToRegex;
36262
36263           this.init = function() {
36264             localeId = $locale.id;
36265
36266             this.parsers = {};
36267 <<<<<<< HEAD
36268             this.formatters = {};
36269 =======
36270 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36271
36272             formatCodeToRegex = [
36273               {
36274                 key: 'yyyy',
36275                 regex: '\\d{4}',
36276 <<<<<<< HEAD
36277                 apply: function(value) { this.year = +value; },
36278                 formatter: function(date) {
36279                   var _date = new Date();
36280                   _date.setFullYear(Math.abs(date.getFullYear()));
36281                   return dateFilter(_date, 'yyyy');
36282                 }
36283 =======
36284                 apply: function(value) { this.year = +value; }
36285 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36286               },
36287               {
36288                 key: 'yy',
36289                 regex: '\\d{2}',
36290 <<<<<<< HEAD
36291                 apply: function(value) { value = +value; this.year = value < 69 ? value + 2000 : value + 1900; },
36292                 formatter: function(date) {
36293                   var _date = new Date();
36294                   _date.setFullYear(Math.abs(date.getFullYear()));
36295                   return dateFilter(_date, 'yy');
36296                 }
36297 =======
36298                 apply: function(value) { this.year = +value + 2000; }
36299 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36300               },
36301               {
36302                 key: 'y',
36303                 regex: '\\d{1,4}',
36304 <<<<<<< HEAD
36305                 apply: function(value) { this.year = +value; },
36306                 formatter: function(date) {
36307                   var _date = new Date();
36308                   _date.setFullYear(Math.abs(date.getFullYear()));
36309                   return dateFilter(_date, 'y');
36310                 }
36311 =======
36312                 apply: function(value) { this.year = +value; }
36313 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36314               },
36315               {
36316                 key: 'M!',
36317                 regex: '0?[1-9]|1[0-2]',
36318 <<<<<<< HEAD
36319                 apply: function(value) { this.month = value - 1; },
36320                 formatter: function(date) {
36321                   var value = date.getMonth();
36322                   if (/^[0-9]$/.test(value)) {
36323                     return dateFilter(date, 'MM');
36324                   }
36325
36326                   return dateFilter(date, 'M');
36327                 }
36328 =======
36329                 apply: function(value) { this.month = value - 1; }
36330 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36331               },
36332               {
36333                 key: 'MMMM',
36334                 regex: $locale.DATETIME_FORMATS.MONTH.join('|'),
36335 <<<<<<< HEAD
36336                 apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); },
36337                 formatter: function(date) { return dateFilter(date, 'MMMM'); }
36338 =======
36339                 apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); }
36340 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36341               },
36342               {
36343                 key: 'MMM',
36344                 regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
36345 <<<<<<< HEAD
36346                 apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); },
36347                 formatter: function(date) { return dateFilter(date, 'MMM'); }
36348 =======
36349                 apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); }
36350 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36351               },
36352               {
36353                 key: 'MM',
36354                 regex: '0[1-9]|1[0-2]',
36355 <<<<<<< HEAD
36356                 apply: function(value) { this.month = value - 1; },
36357                 formatter: function(date) { return dateFilter(date, 'MM'); }
36358 =======
36359                 apply: function(value) { this.month = value - 1; }
36360 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36361               },
36362               {
36363                 key: 'M',
36364                 regex: '[1-9]|1[0-2]',
36365 <<<<<<< HEAD
36366                 apply: function(value) { this.month = value - 1; },
36367                 formatter: function(date) { return dateFilter(date, 'M'); }
36368 =======
36369                 apply: function(value) { this.month = value - 1; }
36370 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36371               },
36372               {
36373                 key: 'd!',
36374                 regex: '[0-2]?[0-9]{1}|3[0-1]{1}',
36375 <<<<<<< HEAD
36376                 apply: function(value) { this.date = +value; },
36377                 formatter: function(date) {
36378                   var value = date.getDate();
36379                   if (/^[1-9]$/.test(value)) {
36380                     return dateFilter(date, 'dd');
36381                   }
36382
36383                   return dateFilter(date, 'd');
36384                 }
36385 =======
36386                 apply: function(value) { this.date = +value; }
36387 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36388               },
36389               {
36390                 key: 'dd',
36391                 regex: '[0-2][0-9]{1}|3[0-1]{1}',
36392 <<<<<<< HEAD
36393                 apply: function(value) { this.date = +value; },
36394                 formatter: function(date) { return dateFilter(date, 'dd'); }
36395 =======
36396                 apply: function(value) { this.date = +value; }
36397 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36398               },
36399               {
36400                 key: 'd',
36401                 regex: '[1-2]?[0-9]{1}|3[0-1]{1}',
36402 <<<<<<< HEAD
36403                 apply: function(value) { this.date = +value; },
36404                 formatter: function(date) { return dateFilter(date, 'd'); }
36405               },
36406               {
36407                 key: 'EEEE',
36408                 regex: $locale.DATETIME_FORMATS.DAY.join('|'),
36409                 formatter: function(date) { return dateFilter(date, 'EEEE'); }
36410               },
36411               {
36412                 key: 'EEE',
36413                 regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
36414                 formatter: function(date) { return dateFilter(date, 'EEE'); }
36415 =======
36416                 apply: function(value) { this.date = +value; }
36417               },
36418               {
36419                 key: 'EEEE',
36420                 regex: $locale.DATETIME_FORMATS.DAY.join('|')
36421               },
36422               {
36423                 key: 'EEE',
36424                 regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|')
36425 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36426               },
36427               {
36428                 key: 'HH',
36429                 regex: '(?:0|1)[0-9]|2[0-3]',
36430 <<<<<<< HEAD
36431                 apply: function(value) { this.hours = +value; },
36432                 formatter: function(date) { return dateFilter(date, 'HH'); }
36433 =======
36434                 apply: function(value) { this.hours = +value; }
36435 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36436               },
36437               {
36438                 key: 'hh',
36439                 regex: '0[0-9]|1[0-2]',
36440 <<<<<<< HEAD
36441                 apply: function(value) { this.hours = +value; },
36442                 formatter: function(date) { return dateFilter(date, 'hh'); }
36443 =======
36444                 apply: function(value) { this.hours = +value; }
36445 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36446               },
36447               {
36448                 key: 'H',
36449                 regex: '1?[0-9]|2[0-3]',
36450 <<<<<<< HEAD
36451                 apply: function(value) { this.hours = +value; },
36452                 formatter: function(date) { return dateFilter(date, 'H'); }
36453 =======
36454                 apply: function(value) { this.hours = +value; }
36455 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36456               },
36457               {
36458                 key: 'h',
36459                 regex: '[0-9]|1[0-2]',
36460 <<<<<<< HEAD
36461                 apply: function(value) { this.hours = +value; },
36462                 formatter: function(date) { return dateFilter(date, 'h'); }
36463 =======
36464                 apply: function(value) { this.hours = +value; }
36465 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36466               },
36467               {
36468                 key: 'mm',
36469                 regex: '[0-5][0-9]',
36470 <<<<<<< HEAD
36471                 apply: function(value) { this.minutes = +value; },
36472                 formatter: function(date) { return dateFilter(date, 'mm'); }
36473 =======
36474                 apply: function(value) { this.minutes = +value; }
36475 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36476               },
36477               {
36478                 key: 'm',
36479                 regex: '[0-9]|[1-5][0-9]',
36480 <<<<<<< HEAD
36481                 apply: function(value) { this.minutes = +value; },
36482                 formatter: function(date) { return dateFilter(date, 'm'); }
36483 =======
36484                 apply: function(value) { this.minutes = +value; }
36485 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36486               },
36487               {
36488                 key: 'sss',
36489                 regex: '[0-9][0-9][0-9]',
36490 <<<<<<< HEAD
36491                 apply: function(value) { this.milliseconds = +value; },
36492                 formatter: function(date) { return dateFilter(date, 'sss'); }
36493 =======
36494                 apply: function(value) { this.milliseconds = +value; }
36495 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36496               },
36497               {
36498                 key: 'ss',
36499                 regex: '[0-5][0-9]',
36500 <<<<<<< HEAD
36501                 apply: function(value) { this.seconds = +value; },
36502                 formatter: function(date) { return dateFilter(date, 'ss'); }
36503 =======
36504                 apply: function(value) { this.seconds = +value; }
36505 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36506               },
36507               {
36508                 key: 's',
36509                 regex: '[0-9]|[1-5][0-9]',
36510 <<<<<<< HEAD
36511                 apply: function(value) { this.seconds = +value; },
36512                 formatter: function(date) { return dateFilter(date, 's'); }
36513 =======
36514                 apply: function(value) { this.seconds = +value; }
36515 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36516               },
36517               {
36518                 key: 'a',
36519                 regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),
36520                 apply: function(value) {
36521                   if (this.hours === 12) {
36522                     this.hours = 0;
36523                   }
36524
36525                   if (value === 'PM') {
36526                     this.hours += 12;
36527                   }
36528 <<<<<<< HEAD
36529                 },
36530                 formatter: function(date) { return dateFilter(date, 'a'); }
36531 =======
36532                 }
36533 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36534               },
36535               {
36536                 key: 'Z',
36537                 regex: '[+-]\\d{4}',
36538                 apply: function(value) {
36539                   var matches = value.match(/([+-])(\d{2})(\d{2})/),
36540                     sign = matches[1],
36541                     hours = matches[2],
36542                     minutes = matches[3];
36543                   this.hours += toInt(sign + hours);
36544                   this.minutes += toInt(sign + minutes);
36545 <<<<<<< HEAD
36546                 },
36547                 formatter: function(date) {
36548                   return dateFilter(date, 'Z');
36549 =======
36550 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36551                 }
36552               },
36553               {
36554                 key: 'ww',
36555 <<<<<<< HEAD
36556                 regex: '[0-4][0-9]|5[0-3]',
36557                 formatter: function(date) { return dateFilter(date, 'ww'); }
36558               },
36559               {
36560                 key: 'w',
36561                 regex: '[0-9]|[1-4][0-9]|5[0-3]',
36562                 formatter: function(date) { return dateFilter(date, 'w'); }
36563               },
36564               {
36565                 key: 'GGGG',
36566                 regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\s/g, '\\s'),
36567                 formatter: function(date) { return dateFilter(date, 'GGGG'); }
36568               },
36569               {
36570                 key: 'GGG',
36571                 regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
36572                 formatter: function(date) { return dateFilter(date, 'GGG'); }
36573               },
36574               {
36575                 key: 'GG',
36576                 regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
36577                 formatter: function(date) { return dateFilter(date, 'GG'); }
36578               },
36579               {
36580                 key: 'G',
36581                 regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
36582                 formatter: function(date) { return dateFilter(date, 'G'); }
36583 =======
36584                 regex: '[0-4][0-9]|5[0-3]'
36585               },
36586               {
36587                 key: 'w',
36588                 regex: '[0-9]|[1-4][0-9]|5[0-3]'
36589               },
36590               {
36591                 key: 'GGGG',
36592                 regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\s/g, '\\s')
36593               },
36594               {
36595                 key: 'GGG',
36596                 regex: $locale.DATETIME_FORMATS.ERAS.join('|')
36597               },
36598               {
36599                 key: 'GG',
36600                 regex: $locale.DATETIME_FORMATS.ERAS.join('|')
36601               },
36602               {
36603                 key: 'G',
36604                 regex: $locale.DATETIME_FORMATS.ERAS.join('|')
36605 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36606               }
36607             ];
36608           };
36609
36610           this.init();
36611
36612 <<<<<<< HEAD
36613           function createParser(format, func) {
36614 =======
36615           function createParser(format) {
36616 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36617             var map = [], regex = format.split('');
36618
36619             // check for literal values
36620             var quoteIndex = format.indexOf('\'');
36621             if (quoteIndex > -1) {
36622               var inLiteral = false;
36623               format = format.split('');
36624               for (var i = quoteIndex; i < format.length; i++) {
36625                 if (inLiteral) {
36626                   if (format[i] === '\'') {
36627                     if (i + 1 < format.length && format[i+1] === '\'') { // escaped single quote
36628                       format[i+1] = '$';
36629                       regex[i+1] = '';
36630                     } else { // end of literal
36631                       regex[i] = '';
36632                       inLiteral = false;
36633                     }
36634                   }
36635                   format[i] = '$';
36636                 } else {
36637                   if (format[i] === '\'') { // start of literal
36638                     format[i] = '$';
36639                     regex[i] = '';
36640                     inLiteral = true;
36641                   }
36642                 }
36643               }
36644
36645               format = format.join('');
36646             }
36647
36648             angular.forEach(formatCodeToRegex, function(data) {
36649               var index = format.indexOf(data.key);
36650
36651               if (index > -1) {
36652                 format = format.split('');
36653
36654                 regex[index] = '(' + data.regex + ')';
36655                 format[index] = '$'; // Custom symbol to define consumed part of format
36656                 for (var i = index + 1, n = index + data.key.length; i < n; i++) {
36657                   regex[i] = '';
36658                   format[i] = '$';
36659                 }
36660                 format = format.join('');
36661
36662                 map.push({
36663                   index: index,
36664 <<<<<<< HEAD
36665                   key: data.key,
36666                   apply: data[func],
36667 =======
36668                   apply: data.apply,
36669 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36670                   matcher: data.regex
36671                 });
36672               }
36673             });
36674
36675             return {
36676               regex: new RegExp('^' + regex.join('') + '$'),
36677               map: orderByFilter(map, 'index')
36678             };
36679           }
36680
36681 <<<<<<< HEAD
36682           this.filter = function(date, format) {
36683             if (!angular.isDate(date) || isNaN(date) || !format) {
36684               return '';
36685             }
36686
36687             format = $locale.DATETIME_FORMATS[format] || format;
36688
36689             if ($locale.id !== localeId) {
36690               this.init();
36691             }
36692
36693             if (!this.formatters[format]) {
36694               this.formatters[format] = createParser(format, 'formatter');
36695             }
36696
36697             var parser = this.formatters[format],
36698               map = parser.map;
36699
36700             var _format = format;
36701
36702             return map.reduce(function(str, mapper, i) {
36703               var match = _format.match(new RegExp('(.*)' + mapper.key));
36704               if (match && angular.isString(match[1])) {
36705                 str += match[1];
36706                 _format = _format.replace(match[1] + mapper.key, '');
36707               }
36708
36709               var endStr = i === map.length - 1 ? _format : '';
36710
36711               if (mapper.apply) {
36712                 return str + mapper.apply.call(null, date) + endStr;
36713               }
36714
36715               return str + endStr;
36716             }, '');
36717           };
36718
36719 =======
36720 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36721           this.parse = function(input, format, baseDate) {
36722             if (!angular.isString(input) || !format) {
36723               return input;
36724             }
36725
36726             format = $locale.DATETIME_FORMATS[format] || format;
36727             format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&');
36728
36729             if ($locale.id !== localeId) {
36730               this.init();
36731             }
36732
36733             if (!this.parsers[format]) {
36734 <<<<<<< HEAD
36735               this.parsers[format] = createParser(format, 'apply');
36736 =======
36737               this.parsers[format] = createParser(format);
36738 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36739             }
36740
36741             var parser = this.parsers[format],
36742                 regex = parser.regex,
36743                 map = parser.map,
36744                 results = input.match(regex),
36745                 tzOffset = false;
36746             if (results && results.length) {
36747               var fields, dt;
36748               if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {
36749                 fields = {
36750                   year: baseDate.getFullYear(),
36751                   month: baseDate.getMonth(),
36752                   date: baseDate.getDate(),
36753                   hours: baseDate.getHours(),
36754                   minutes: baseDate.getMinutes(),
36755                   seconds: baseDate.getSeconds(),
36756                   milliseconds: baseDate.getMilliseconds()
36757                 };
36758               } else {
36759                 if (baseDate) {
36760                   $log.warn('dateparser:', 'baseDate is not a valid date');
36761                 }
36762                 fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
36763               }
36764
36765               for (var i = 1, n = results.length; i < n; i++) {
36766                 var mapper = map[i - 1];
36767                 if (mapper.matcher === 'Z') {
36768                   tzOffset = true;
36769                 }
36770
36771                 if (mapper.apply) {
36772                   mapper.apply.call(fields, results[i]);
36773                 }
36774               }
36775
36776               var datesetter = tzOffset ? Date.prototype.setUTCFullYear :
36777                 Date.prototype.setFullYear;
36778               var timesetter = tzOffset ? Date.prototype.setUTCHours :
36779                 Date.prototype.setHours;
36780
36781               if (isValid(fields.year, fields.month, fields.date)) {
36782                 if (angular.isDate(baseDate) && !isNaN(baseDate.getTime()) && !tzOffset) {
36783                   dt = new Date(baseDate);
36784                   datesetter.call(dt, fields.year, fields.month, fields.date);
36785                   timesetter.call(dt, fields.hours, fields.minutes,
36786                     fields.seconds, fields.milliseconds);
36787                 } else {
36788                   dt = new Date(0);
36789                   datesetter.call(dt, fields.year, fields.month, fields.date);
36790                   timesetter.call(dt, fields.hours || 0, fields.minutes || 0,
36791                     fields.seconds || 0, fields.milliseconds || 0);
36792                 }
36793               }
36794
36795               return dt;
36796             }
36797           };
36798
36799           // Check if date is valid for specific month (and year for February).
36800           // Month: 0 = Jan, 1 = Feb, etc
36801           function isValid(year, month, date) {
36802             if (date < 1) {
36803               return false;
36804             }
36805
36806             if (month === 1 && date > 28) {
36807               return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0);
36808             }
36809
36810             if (month === 3 || month === 5 || month === 8 || month === 10) {
36811               return date < 31;
36812             }
36813
36814             return true;
36815           }
36816
36817           function toInt(str) {
36818             return parseInt(str, 10);
36819           }
36820
36821           this.toTimezone = toTimezone;
36822           this.fromTimezone = fromTimezone;
36823           this.timezoneToOffset = timezoneToOffset;
36824           this.addDateMinutes = addDateMinutes;
36825           this.convertTimezoneToLocal = convertTimezoneToLocal;
36826 <<<<<<< HEAD
36827
36828 =======
36829           
36830 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36831           function toTimezone(date, timezone) {
36832             return date && timezone ? convertTimezoneToLocal(date, timezone) : date;
36833           }
36834
36835           function fromTimezone(date, timezone) {
36836             return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;
36837           }
36838
36839 <<<<<<< HEAD
36840           //https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207
36841           function timezoneToOffset(timezone, fallback) {
36842             timezone = timezone.replace(/:/g, '');
36843 =======
36844           //https://github.com/angular/angular.js/blob/4daafd3dbe6a80d578f5a31df1bb99c77559543e/src/Angular.js#L1207
36845           function timezoneToOffset(timezone, fallback) {
36846 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36847             var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
36848             return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
36849           }
36850
36851           function addDateMinutes(date, minutes) {
36852             date = new Date(date.getTime());
36853             date.setMinutes(date.getMinutes() + minutes);
36854             return date;
36855           }
36856
36857           function convertTimezoneToLocal(date, timezone, reverse) {
36858             reverse = reverse ? -1 : 1;
36859 <<<<<<< HEAD
36860             var dateTimezoneOffset = date.getTimezoneOffset();
36861             var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
36862             return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
36863 =======
36864             var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
36865             return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset()));
36866 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36867           }
36868         }]);
36869
36870         // Avoiding use of ng-class as it creates a lot of watchers when a class is to be applied to
36871         // at most one element.
36872         angular.module('ui.bootstrap.isClass', [])
36873         .directive('uibIsClass', [
36874                  '$animate',
36875         function ($animate) {
36876           //                    11111111          22222222
36877           var ON_REGEXP = /^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/;
36878           //                    11111111           22222222
36879           var IS_REGEXP = /^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;
36880
36881           var dataPerTracked = {};
36882
36883           return {
36884             restrict: 'A',
36885 <<<<<<< HEAD
36886             compile: function(tElement, tAttrs) {
36887 =======
36888             compile: function (tElement, tAttrs) {
36889 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36890               var linkedScopes = [];
36891               var instances = [];
36892               var expToData = {};
36893               var lastActivated = null;
36894               var onExpMatches = tAttrs.uibIsClass.match(ON_REGEXP);
36895               var onExp = onExpMatches[2];
36896               var expsStr = onExpMatches[1];
36897               var exps = expsStr.split(',');
36898
36899               return linkFn;
36900
36901               function linkFn(scope, element, attrs) {
36902                 linkedScopes.push(scope);
36903                 instances.push({
36904                   scope: scope,
36905                   element: element
36906                 });
36907
36908 <<<<<<< HEAD
36909                 exps.forEach(function(exp, k) {
36910 =======
36911                 exps.forEach(function (exp, k) {
36912 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36913                   addForExp(exp, scope);
36914                 });
36915
36916                 scope.$on('$destroy', removeScope);
36917               }
36918
36919               function addForExp(exp, scope) {
36920                 var matches = exp.match(IS_REGEXP);
36921                 var clazz = scope.$eval(matches[1]);
36922                 var compareWithExp = matches[2];
36923                 var data = expToData[exp];
36924                 if (!data) {
36925 <<<<<<< HEAD
36926                   var watchFn = function(compareWithVal) {
36927                     var newActivated = null;
36928                     instances.some(function(instance) {
36929 =======
36930                   var watchFn = function (compareWithVal) {
36931                     var newActivated = null;
36932                     instances.some(function (instance) {
36933 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36934                       var thisVal = instance.scope.$eval(onExp);
36935                       if (thisVal === compareWithVal) {
36936                         newActivated = instance;
36937                         return true;
36938                       }
36939                     });
36940                     if (data.lastActivated !== newActivated) {
36941                       if (data.lastActivated) {
36942                         $animate.removeClass(data.lastActivated.element, clazz);
36943                       }
36944                       if (newActivated) {
36945                         $animate.addClass(newActivated.element, clazz);
36946                       }
36947                       data.lastActivated = newActivated;
36948                     }
36949                   };
36950                   expToData[exp] = data = {
36951                     lastActivated: null,
36952                     scope: scope,
36953                     watchFn: watchFn,
36954                     compareWithExp: compareWithExp,
36955                     watcher: scope.$watch(compareWithExp, watchFn)
36956                   };
36957                 }
36958                 data.watchFn(scope.$eval(compareWithExp));
36959               }
36960
36961               function removeScope(e) {
36962                 var removedScope = e.targetScope;
36963                 var index = linkedScopes.indexOf(removedScope);
36964                 linkedScopes.splice(index, 1);
36965                 instances.splice(index, 1);
36966                 if (linkedScopes.length) {
36967                   var newWatchScope = linkedScopes[0];
36968 <<<<<<< HEAD
36969                   angular.forEach(expToData, function(data) {
36970 =======
36971                   angular.forEach(expToData, function (data) {
36972 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36973                     if (data.scope === removedScope) {
36974                       data.watcher = newWatchScope.$watch(data.compareWithExp, data.watchFn);
36975                       data.scope = newWatchScope;
36976                     }
36977                   });
36978 <<<<<<< HEAD
36979                 } else {
36980 =======
36981                 }
36982                 else {
36983 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
36984                   expToData = {};
36985                 }
36986               }
36987             }
36988           };
36989         }]);
36990 <<<<<<< HEAD
36991         angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass'])
36992
36993         .value('$datepickerSuppressError', false)
36994
36995         .value('$datepickerLiteralWarning', true)
36996
36997         .constant('uibDatepickerConfig', {
36998           datepickerMode: 'day',
36999           formatDay: 'dd',
37000           formatMonth: 'MMMM',
37001           formatYear: 'yyyy',
37002           formatDayHeader: 'EEE',
37003           formatDayTitle: 'MMMM yyyy',
37004           formatMonthTitle: 'yyyy',
37005           maxDate: null,
37006           maxMode: 'year',
37007           minDate: null,
37008           minMode: 'day',
37009           ngModelOptions: {},
37010           shortcutPropagation: false,
37011           showWeeks: true,
37012           yearColumns: 5,
37013           yearRows: 4
37014         })
37015
37016         .controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
37017           function($scope, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
37018           var self = this,
37019               ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
37020               ngModelOptions = {},
37021               watchListeners = [],
37022               optionsUsed = !!$attrs.datepickerOptions;
37023
37024           if (!$scope.datepickerOptions) {
37025             $scope.datepickerOptions = {};
37026           }
37027
37028           // Modes chain
37029           this.modes = ['day', 'month', 'year'];
37030
37031           [
37032             'customClass',
37033             'dateDisabled',
37034             'datepickerMode',
37035             'formatDay',
37036             'formatDayHeader',
37037             'formatDayTitle',
37038             'formatMonth',
37039             'formatMonthTitle',
37040             'formatYear',
37041             'maxDate',
37042             'maxMode',
37043             'minDate',
37044             'minMode',
37045             'showWeeks',
37046             'shortcutPropagation',
37047             'startingDay',
37048             'yearColumns',
37049             'yearRows'
37050           ].forEach(function(key) {
37051             switch (key) {
37052               case 'customClass':
37053               case 'dateDisabled':
37054                 $scope[key] = $scope.datepickerOptions[key] || angular.noop;
37055                 break;
37056               case 'datepickerMode':
37057                 $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ?
37058                   $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode;
37059                 break;
37060               case 'formatDay':
37061               case 'formatDayHeader':
37062               case 'formatDayTitle':
37063               case 'formatMonth':
37064               case 'formatMonthTitle':
37065               case 'formatYear':
37066                 self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
37067                   $interpolate($scope.datepickerOptions[key])($scope.$parent) :
37068                   datepickerConfig[key];
37069                 break;
37070               case 'showWeeks':
37071               case 'shortcutPropagation':
37072               case 'yearColumns':
37073               case 'yearRows':
37074                 self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
37075                   $scope.datepickerOptions[key] : datepickerConfig[key];
37076                 break;
37077               case 'startingDay':
37078                 if (angular.isDefined($scope.datepickerOptions.startingDay)) {
37079                   self.startingDay = $scope.datepickerOptions.startingDay;
37080                 } else if (angular.isNumber(datepickerConfig.startingDay)) {
37081                   self.startingDay = datepickerConfig.startingDay;
37082                 } else {
37083                   self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
37084                 }
37085
37086                 break;
37087               case 'maxDate':
37088               case 'minDate':
37089                 $scope.$watch('datepickerOptions.' + key, function(value) {
37090                   if (value) {
37091                     if (angular.isDate(value)) {
37092                       self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone);
37093                     } else {
37094                       if ($datepickerLiteralWarning) {
37095                         $log.warn('Literal date support has been deprecated, please switch to date object usage');
37096                       }
37097
37098                       self[key] = new Date(dateFilter(value, 'medium'));
37099                     }
37100                   } else {
37101                     self[key] = datepickerConfig[key] ?
37102                       dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) :
37103                       null;
37104                   }
37105
37106                   self.refreshView();
37107                 });
37108
37109                 break;
37110               case 'maxMode':
37111               case 'minMode':
37112                 if ($scope.datepickerOptions[key]) {
37113                   $scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {
37114                     self[key] = $scope[key] = angular.isDefined(value) ? value : datepickerOptions[key];
37115                     if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||
37116                       key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {
37117                       $scope.datepickerMode = self[key];
37118                       $scope.datepickerOptions.datepickerMode = self[key];
37119                     }
37120                   });
37121                 } else {
37122                   self[key] = $scope[key] = datepickerConfig[key] || null;
37123                 }
37124
37125                 break;
37126             }
37127           });
37128
37129           $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
37130
37131           $scope.disabled = angular.isDefined($attrs.disabled) || false;
37132           if (angular.isDefined($attrs.ngDisabled)) {
37133             watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) {
37134               $scope.disabled = disabled;
37135               self.refreshView();
37136             }));
37137           }
37138
37139           $scope.isActive = function(dateObject) {
37140             if (self.compare(dateObject.date, self.activeDate) === 0) {
37141               $scope.activeDateId = dateObject.uid;
37142               return true;
37143             }
37144             return false;
37145           };
37146
37147           this.init = function(ngModelCtrl_) {
37148             ngModelCtrl = ngModelCtrl_;
37149             ngModelOptions = ngModelCtrl_.$options || datepickerConfig.ngModelOptions;
37150             if ($scope.datepickerOptions.initDate) {
37151               self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date();
37152               $scope.$watch('datepickerOptions.initDate', function(initDate) {
37153                 if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
37154                   self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
37155                   self.refreshView();
37156                 }
37157               });
37158             } else {
37159               self.activeDate = new Date();
37160             }
37161
37162             var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
37163             this.activeDate = !isNaN(date) ?
37164               dateParser.fromTimezone(date, ngModelOptions.timezone) :
37165               dateParser.fromTimezone(new Date(), ngModelOptions.timezone);
37166
37167             ngModelCtrl.$render = function() {
37168               self.render();
37169             };
37170           };
37171
37172           this.render = function() {
37173             if (ngModelCtrl.$viewValue) {
37174               var date = new Date(ngModelCtrl.$viewValue),
37175                   isValid = !isNaN(date);
37176
37177               if (isValid) {
37178                 this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone);
37179               } else if (!$datepickerSuppressError) {
37180                 $log.error('Datepicker directive: "ng-model" value must be a Date object');
37181               }
37182             }
37183             this.refreshView();
37184           };
37185
37186           this.refreshView = function() {
37187             if (this.element) {
37188               $scope.selectedDt = null;
37189               this._refreshView();
37190               if ($scope.activeDt) {
37191                 $scope.activeDateId = $scope.activeDt.uid;
37192               }
37193
37194               var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
37195               date = dateParser.fromTimezone(date, ngModelOptions.timezone);
37196               ngModelCtrl.$setValidity('dateDisabled', !date ||
37197                 this.element && !this.isDisabled(date));
37198             }
37199           };
37200
37201           this.createDateObject = function(date, format) {
37202             var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
37203             model = dateParser.fromTimezone(model, ngModelOptions.timezone);
37204             var today = new Date();
37205             today = dateParser.fromTimezone(today, ngModelOptions.timezone);
37206             var time = this.compare(date, today);
37207             var dt = {
37208               date: date,
37209               label: dateParser.filter(date, format),
37210               selected: model && this.compare(date, model) === 0,
37211               disabled: this.isDisabled(date),
37212               past: time < 0,
37213               current: time === 0,
37214               future: time > 0,
37215               customClass: this.customClass(date) || null
37216             };
37217
37218             if (model && this.compare(date, model) === 0) {
37219               $scope.selectedDt = dt;
37220             }
37221
37222             if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {
37223               $scope.activeDt = dt;
37224             }
37225
37226             return dt;
37227           };
37228
37229           this.isDisabled = function(date) {
37230             return $scope.disabled ||
37231               this.minDate && this.compare(date, this.minDate) < 0 ||
37232               this.maxDate && this.compare(date, this.maxDate) > 0 ||
37233               $scope.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode});
37234           };
37235
37236           this.customClass = function(date) {
37237             return $scope.customClass({date: date, mode: $scope.datepickerMode});
37238           };
37239
37240           // Split array into smaller arrays
37241           this.split = function(arr, size) {
37242             var arrays = [];
37243             while (arr.length > 0) {
37244               arrays.push(arr.splice(0, size));
37245             }
37246             return arrays;
37247           };
37248
37249           $scope.select = function(date) {
37250             if ($scope.datepickerMode === self.minMode) {
37251               var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0);
37252               dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
37253               dt = dateParser.toTimezone(dt, ngModelOptions.timezone);
37254               ngModelCtrl.$setViewValue(dt);
37255               ngModelCtrl.$render();
37256             } else {
37257               self.activeDate = date;
37258               setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);
37259
37260               $scope.$emit('uib:datepicker.mode');
37261             }
37262
37263             $scope.$broadcast('uib:datepicker.focus');
37264           };
37265
37266           $scope.move = function(direction) {
37267             var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
37268                 month = self.activeDate.getMonth() + direction * (self.step.months || 0);
37269             self.activeDate.setFullYear(year, month, 1);
37270             self.refreshView();
37271           };
37272
37273           $scope.toggleMode = function(direction) {
37274             direction = direction || 1;
37275
37276             if ($scope.datepickerMode === self.maxMode && direction === 1 ||
37277               $scope.datepickerMode === self.minMode && direction === -1) {
37278               return;
37279             }
37280
37281             setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]);
37282
37283             $scope.$emit('uib:datepicker.mode');
37284 =======
37285         angular.module('ui.bootstrap.position', [])
37286
37287         /**
37288          * A set of utility methods for working with the DOM.
37289          * It is meant to be used where we need to absolute-position elements in
37290          * relation to another element (this is the case for tooltips, popovers,
37291          * typeahead suggestions etc.).
37292          */
37293           .factory('$uibPosition', ['$document', '$window', function($document, $window) {
37294             /**
37295              * Used by scrollbarWidth() function to cache scrollbar's width.
37296              * Do not access this variable directly, use scrollbarWidth() instead.
37297              */
37298             var SCROLLBAR_WIDTH;
37299             var OVERFLOW_REGEX = {
37300               normal: /(auto|scroll)/,
37301               hidden: /(auto|scroll|hidden)/
37302             };
37303             var PLACEMENT_REGEX = {
37304               auto: /\s?auto?\s?/i,
37305               primary: /^(top|bottom|left|right)$/,
37306               secondary: /^(top|bottom|left|right|center)$/,
37307               vertical: /^(top|bottom)$/
37308             };
37309
37310             return {
37311
37312               /**
37313                * Provides a raw DOM element from a jQuery/jQLite element.
37314                *
37315                * @param {element} elem - The element to convert.
37316                *
37317                * @returns {element} A HTML element.
37318                */
37319               getRawNode: function(elem) {
37320                 return elem[0] || elem;
37321               },
37322
37323               /**
37324                * Provides a parsed number for a style property.  Strips
37325                * units and casts invalid numbers to 0.
37326                *
37327                * @param {string} value - The style value to parse.
37328                *
37329                * @returns {number} A valid number.
37330                */
37331               parseStyle: function(value) {
37332                 value = parseFloat(value);
37333                 return isFinite(value) ? value : 0;
37334               },
37335
37336               /**
37337                * Provides the closest positioned ancestor.
37338                *
37339                * @param {element} element - The element to get the offest parent for.
37340                *
37341                * @returns {element} The closest positioned ancestor.
37342                */
37343               offsetParent: function(elem) {
37344                 elem = this.getRawNode(elem);
37345
37346                 var offsetParent = elem.offsetParent || $document[0].documentElement;
37347
37348                 function isStaticPositioned(el) {
37349                   return ($window.getComputedStyle(el).position || 'static') === 'static';
37350                 }
37351
37352                 while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {
37353                   offsetParent = offsetParent.offsetParent;
37354                 }
37355
37356                 return offsetParent || $document[0].documentElement;
37357               },
37358
37359               /**
37360                * Provides the scrollbar width, concept from TWBS measureScrollbar()
37361                * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js
37362                *
37363                * @returns {number} The width of the browser scollbar.
37364                */
37365               scrollbarWidth: function() {
37366                 if (angular.isUndefined(SCROLLBAR_WIDTH)) {
37367                   var scrollElem = angular.element('<div style="position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll;"></div>');
37368                   $document.find('body').append(scrollElem);
37369                   SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;
37370                   SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;
37371                   scrollElem.remove();
37372                 }
37373
37374                 return SCROLLBAR_WIDTH;
37375               },
37376
37377               /**
37378                * Provides the closest scrollable ancestor.
37379                * A port of the jQuery UI scrollParent method:
37380                * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
37381                *
37382                * @param {element} elem - The element to find the scroll parent of.
37383                * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
37384                *   default is false.
37385                *
37386                * @returns {element} A HTML element.
37387                */
37388               scrollParent: function(elem, includeHidden) {
37389                 elem = this.getRawNode(elem);
37390
37391                 var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
37392                 var documentEl = $document[0].documentElement;
37393                 var elemStyle = $window.getComputedStyle(elem);
37394                 var excludeStatic = elemStyle.position === 'absolute';
37395                 var scrollParent = elem.parentElement || documentEl;
37396
37397                 if (scrollParent === documentEl || elemStyle.position === 'fixed') {
37398                   return documentEl;
37399                 }
37400
37401                 while (scrollParent.parentElement && scrollParent !== documentEl) {
37402                   var spStyle = $window.getComputedStyle(scrollParent);
37403                   if (excludeStatic && spStyle.position !== 'static') {
37404                     excludeStatic = false;
37405                   }
37406
37407                   if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
37408                     break;
37409                   }
37410                   scrollParent = scrollParent.parentElement;
37411                 }
37412
37413                 return scrollParent;
37414               },
37415
37416               /**
37417                * Provides read-only equivalent of jQuery's position function:
37418                * http://api.jquery.com/position/ - distance to closest positioned
37419                * ancestor.  Does not account for margins by default like jQuery position.
37420                *
37421                * @param {element} elem - The element to caclulate the position on.
37422                * @param {boolean=} [includeMargins=false] - Should margins be accounted
37423                * for, default is false.
37424                *
37425                * @returns {object} An object with the following properties:
37426                *   <ul>
37427                *     <li>**width**: the width of the element</li>
37428                *     <li>**height**: the height of the element</li>
37429                *     <li>**top**: distance to top edge of offset parent</li>
37430                *     <li>**left**: distance to left edge of offset parent</li>
37431                *   </ul>
37432                */
37433               position: function(elem, includeMagins) {
37434                 elem = this.getRawNode(elem);
37435
37436                 var elemOffset = this.offset(elem);
37437                 if (includeMagins) {
37438                   var elemStyle = $window.getComputedStyle(elem);
37439                   elemOffset.top -= this.parseStyle(elemStyle.marginTop);
37440                   elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
37441                 }
37442                 var parent = this.offsetParent(elem);
37443                 var parentOffset = {top: 0, left: 0};
37444
37445                 if (parent !== $document[0].documentElement) {
37446                   parentOffset = this.offset(parent);
37447                   parentOffset.top += parent.clientTop - parent.scrollTop;
37448                   parentOffset.left += parent.clientLeft - parent.scrollLeft;
37449                 }
37450
37451                 return {
37452                   width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
37453                   height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
37454                   top: Math.round(elemOffset.top - parentOffset.top),
37455                   left: Math.round(elemOffset.left - parentOffset.left)
37456                 };
37457               },
37458
37459               /**
37460                * Provides read-only equivalent of jQuery's offset function:
37461                * http://api.jquery.com/offset/ - distance to viewport.  Does
37462                * not account for borders, margins, or padding on the body
37463                * element.
37464                *
37465                * @param {element} elem - The element to calculate the offset on.
37466                *
37467                * @returns {object} An object with the following properties:
37468                *   <ul>
37469                *     <li>**width**: the width of the element</li>
37470                *     <li>**height**: the height of the element</li>
37471                *     <li>**top**: distance to top edge of viewport</li>
37472                *     <li>**right**: distance to bottom edge of viewport</li>
37473                *   </ul>
37474                */
37475               offset: function(elem) {
37476                 elem = this.getRawNode(elem);
37477
37478                 var elemBCR = elem.getBoundingClientRect();
37479                 return {
37480                   width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
37481                   height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
37482                   top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
37483                   left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
37484                 };
37485               },
37486
37487               /**
37488                * Provides offset distance to the closest scrollable ancestor
37489                * or viewport.  Accounts for border and scrollbar width.
37490                *
37491                * Right and bottom dimensions represent the distance to the
37492                * respective edge of the viewport element.  If the element
37493                * edge extends beyond the viewport, a negative value will be
37494                * reported.
37495                *
37496                * @param {element} elem - The element to get the viewport offset for.
37497                * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
37498                * of the first scrollable element, default is false.
37499                * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
37500                * be accounted for, default is true.
37501                *
37502                * @returns {object} An object with the following properties:
37503                *   <ul>
37504                *     <li>**top**: distance to the top content edge of viewport element</li>
37505                *     <li>**bottom**: distance to the bottom content edge of viewport element</li>
37506                *     <li>**left**: distance to the left content edge of viewport element</li>
37507                *     <li>**right**: distance to the right content edge of viewport element</li>
37508                *   </ul>
37509                */
37510               viewportOffset: function(elem, useDocument, includePadding) {
37511                 elem = this.getRawNode(elem);
37512                 includePadding = includePadding !== false ? true : false;
37513
37514                 var elemBCR = elem.getBoundingClientRect();
37515                 var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};
37516
37517                 var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
37518                 var offsetParentBCR = offsetParent.getBoundingClientRect();
37519
37520                 offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
37521                 offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
37522                 if (offsetParent === $document[0].documentElement) {
37523                   offsetBCR.top += $window.pageYOffset;
37524                   offsetBCR.left += $window.pageXOffset;
37525                 }
37526                 offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
37527                 offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;
37528
37529                 if (includePadding) {
37530                   var offsetParentStyle = $window.getComputedStyle(offsetParent);
37531                   offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
37532                   offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
37533                   offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
37534                   offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
37535                 }
37536
37537                 return {
37538                   top: Math.round(elemBCR.top - offsetBCR.top),
37539                   bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
37540                   left: Math.round(elemBCR.left - offsetBCR.left),
37541                   right: Math.round(offsetBCR.right - elemBCR.right)
37542                 };
37543               },
37544
37545               /**
37546                * Provides an array of placement values parsed from a placement string.
37547                * Along with the 'auto' indicator, supported placement strings are:
37548                *   <ul>
37549                *     <li>top: element on top, horizontally centered on host element.</li>
37550                *     <li>top-left: element on top, left edge aligned with host element left edge.</li>
37551                *     <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>
37552                *     <li>bottom: element on bottom, horizontally centered on host element.</li>
37553                *     <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>
37554                *     <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>
37555                *     <li>left: element on left, vertically centered on host element.</li>
37556                *     <li>left-top: element on left, top edge aligned with host element top edge.</li>
37557                *     <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>
37558                *     <li>right: element on right, vertically centered on host element.</li>
37559                *     <li>right-top: element on right, top edge aligned with host element top edge.</li>
37560                *     <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>
37561                *   </ul>
37562                * A placement string with an 'auto' indicator is expected to be
37563                * space separated from the placement, i.e: 'auto bottom-left'  If
37564                * the primary and secondary placement values do not match 'top,
37565                * bottom, left, right' then 'top' will be the primary placement and
37566                * 'center' will be the secondary placement.  If 'auto' is passed, true
37567                * will be returned as the 3rd value of the array.
37568                *
37569                * @param {string} placement - The placement string to parse.
37570                *
37571                * @returns {array} An array with the following values
37572                * <ul>
37573                *   <li>**[0]**: The primary placement.</li>
37574                *   <li>**[1]**: The secondary placement.</li>
37575                *   <li>**[2]**: If auto is passed: true, else undefined.</li>
37576                * </ul>
37577                */
37578               parsePlacement: function(placement) {
37579                 var autoPlace = PLACEMENT_REGEX.auto.test(placement);
37580                 if (autoPlace) {
37581                   placement = placement.replace(PLACEMENT_REGEX.auto, '');
37582                 }
37583
37584                 placement = placement.split('-');
37585
37586                 placement[0] = placement[0] || 'top';
37587                 if (!PLACEMENT_REGEX.primary.test(placement[0])) {
37588                   placement[0] = 'top';
37589                 }
37590
37591                 placement[1] = placement[1] || 'center';
37592                 if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
37593                   placement[1] = 'center';
37594                 }
37595
37596                 if (autoPlace) {
37597                   placement[2] = true;
37598                 } else {
37599                   placement[2] = false;
37600                 }
37601
37602                 return placement;
37603               },
37604
37605               /**
37606                * Provides coordinates for an element to be positioned relative to
37607                * another element.  Passing 'auto' as part of the placement parameter
37608                * will enable smart placement - where the element fits. i.e:
37609                * 'auto left-top' will check to see if there is enough space to the left
37610                * of the hostElem to fit the targetElem, if not place right (same for secondary
37611                * top placement).  Available space is calculated using the viewportOffset
37612                * function.
37613                *
37614                * @param {element} hostElem - The element to position against.
37615                * @param {element} targetElem - The element to position.
37616                * @param {string=} [placement=top] - The placement for the targetElem,
37617                *   default is 'top'. 'center' is assumed as secondary placement for
37618                *   'top', 'left', 'right', and 'bottom' placements.  Available placements are:
37619                *   <ul>
37620                *     <li>top</li>
37621                *     <li>top-right</li>
37622                *     <li>top-left</li>
37623                *     <li>bottom</li>
37624                *     <li>bottom-left</li>
37625                *     <li>bottom-right</li>
37626                *     <li>left</li>
37627                *     <li>left-top</li>
37628                *     <li>left-bottom</li>
37629                *     <li>right</li>
37630                *     <li>right-top</li>
37631                *     <li>right-bottom</li>
37632                *   </ul>
37633                * @param {boolean=} [appendToBody=false] - Should the top and left values returned
37634                *   be calculated from the body element, default is false.
37635                *
37636                * @returns {object} An object with the following properties:
37637                *   <ul>
37638                *     <li>**top**: Value for targetElem top.</li>
37639                *     <li>**left**: Value for targetElem left.</li>
37640                *     <li>**placement**: The resolved placement.</li>
37641                *   </ul>
37642                */
37643               positionElements: function(hostElem, targetElem, placement, appendToBody) {
37644                 hostElem = this.getRawNode(hostElem);
37645                 targetElem = this.getRawNode(targetElem);
37646
37647                 // need to read from prop to support tests.
37648                 var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
37649                 var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');
37650
37651                 placement = this.parsePlacement(placement);
37652
37653                 var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
37654                 var targetElemPos = {top: 0, left: 0, placement: ''};
37655
37656                 if (placement[2]) {
37657                   var viewportOffset = this.viewportOffset(hostElem);
37658
37659                   var targetElemStyle = $window.getComputedStyle(targetElem);
37660                   var adjustedSize = {
37661                     width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
37662                     height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
37663                   };
37664
37665                   placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
37666                                  placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
37667                                  placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
37668                                  placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
37669                                  placement[0];
37670
37671                   placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
37672                                  placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
37673                                  placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
37674                                  placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
37675                                  placement[1];
37676
37677                   if (placement[1] === 'center') {
37678                     if (PLACEMENT_REGEX.vertical.test(placement[0])) {
37679                       var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
37680                       if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
37681                         placement[1] = 'left';
37682                       } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
37683                         placement[1] = 'right';
37684                       }
37685                     } else {
37686                       var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
37687                       if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
37688                         placement[1] = 'top';
37689                       } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
37690                         placement[1] = 'bottom';
37691                       }
37692                     }
37693                   }
37694                 }
37695
37696                 switch (placement[0]) {
37697                   case 'top':
37698                     targetElemPos.top = hostElemPos.top - targetHeight;
37699                     break;
37700                   case 'bottom':
37701                     targetElemPos.top = hostElemPos.top + hostElemPos.height;
37702                     break;
37703                   case 'left':
37704                     targetElemPos.left = hostElemPos.left - targetWidth;
37705                     break;
37706                   case 'right':
37707                     targetElemPos.left = hostElemPos.left + hostElemPos.width;
37708                     break;
37709                 }
37710
37711                 switch (placement[1]) {
37712                   case 'top':
37713                     targetElemPos.top = hostElemPos.top;
37714                     break;
37715                   case 'bottom':
37716                     targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
37717                     break;
37718                   case 'left':
37719                     targetElemPos.left = hostElemPos.left;
37720                     break;
37721                   case 'right':
37722                     targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
37723                     break;
37724                   case 'center':
37725                     if (PLACEMENT_REGEX.vertical.test(placement[0])) {
37726                       targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
37727                     } else {
37728                       targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
37729                     }
37730                     break;
37731                 }
37732
37733                 targetElemPos.top = Math.round(targetElemPos.top);
37734                 targetElemPos.left = Math.round(targetElemPos.left);
37735                 targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];
37736
37737                 return targetElemPos;
37738               },
37739
37740               /**
37741               * Provides a way for positioning tooltip & dropdown
37742               * arrows when using placement options beyond the standard
37743               * left, right, top, or bottom.
37744               *
37745               * @param {element} elem - The tooltip/dropdown element.
37746               * @param {string} placement - The placement for the elem.
37747               */
37748               positionArrow: function(elem, placement) {
37749                 elem = this.getRawNode(elem);
37750
37751                 var isTooltip = true;
37752
37753                 var innerElem = elem.querySelector('.tooltip-inner');
37754                 if (!innerElem) {
37755                   isTooltip = false;
37756                   innerElem = elem.querySelector('.popover-inner');
37757                 }
37758                 if (!innerElem) {
37759                   return;
37760                 }
37761
37762                 var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
37763                 if (!arrowElem) {
37764                   return;
37765                 }
37766
37767                 placement = this.parsePlacement(placement);
37768                 if (placement[1] === 'center') {
37769                   // no adjustment necessary - just reset styles
37770                   angular.element(arrowElem).css({top: '', bottom: '', right: '', left: '', margin: ''});
37771                   return;
37772                 }
37773
37774                 var borderProp = 'border-' + placement[0] + '-width';
37775                 var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];
37776
37777                 var borderRadiusProp = 'border-';
37778                 if (PLACEMENT_REGEX.vertical.test(placement[0])) {
37779                   borderRadiusProp += placement[0] + '-' + placement[1];
37780                 } else {
37781                   borderRadiusProp += placement[1] + '-' + placement[0];
37782                 }
37783                 borderRadiusProp += '-radius';
37784                 var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];
37785
37786                 var arrowCss = {
37787                   top: 'auto',
37788                   bottom: 'auto',
37789                   left: 'auto',
37790                   right: 'auto',
37791                   margin: 0
37792                 };
37793
37794                 switch (placement[0]) {
37795                   case 'top':
37796                     arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
37797                     break;
37798                   case 'bottom':
37799                     arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
37800                     break;
37801                   case 'left':
37802                     arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
37803                     break;
37804                   case 'right':
37805                     arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
37806                     break;
37807                 }
37808
37809                 arrowCss[placement[1]] = borderRadius;
37810
37811                 angular.element(arrowElem).css(arrowCss);
37812               }
37813             };
37814           }]);
37815
37816         angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass', 'ui.bootstrap.position'])
37817
37818         .value('$datepickerSuppressError', false)
37819
37820         .constant('uibDatepickerConfig', {
37821           formatDay: 'dd',
37822           formatMonth: 'MMMM',
37823           formatYear: 'yyyy',
37824           formatDayHeader: 'EEE',
37825           formatDayTitle: 'MMMM yyyy',
37826           formatMonthTitle: 'yyyy',
37827           datepickerMode: 'day',
37828           minMode: 'day',
37829           maxMode: 'year',
37830           showWeeks: true,
37831           startingDay: 0,
37832           yearRows: 4,
37833           yearColumns: 5,
37834           minDate: null,
37835           maxDate: null,
37836           shortcutPropagation: false,
37837           ngModelOptions: {}
37838         })
37839
37840         .controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerSuppressError', 'uibDateParser',
37841           function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError, dateParser) {
37842           var self = this,
37843               ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
37844               ngModelOptions = {};
37845
37846           // Modes chain
37847           this.modes = ['day', 'month', 'year'];
37848
37849           // Interpolated configuration attributes
37850           angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle'], function(key) {
37851             self[key] = angular.isDefined($attrs[key]) ? $interpolate($attrs[key])($scope.$parent) : datepickerConfig[key];
37852           });
37853
37854           // Evaled configuration attributes
37855           angular.forEach(['showWeeks', 'startingDay', 'yearRows', 'yearColumns', 'shortcutPropagation'], function(key) {
37856             self[key] = angular.isDefined($attrs[key]) ? $scope.$parent.$eval($attrs[key]) : datepickerConfig[key];
37857           });
37858
37859           // Watchable date attributes
37860           angular.forEach(['minDate', 'maxDate'], function(key) {
37861             if ($attrs[key]) {
37862               $scope.$parent.$watch($attrs[key], function(value) {
37863                 self[key] = value ? angular.isDate(value) ? dateParser.fromTimezone(new Date(value), ngModelOptions.timezone) : new Date(dateFilter(value, 'medium')) : null;
37864                 self.refreshView();
37865               });
37866             } else {
37867               self[key] = datepickerConfig[key] ? dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) : null;
37868             }
37869           });
37870
37871           angular.forEach(['minMode', 'maxMode'], function(key) {
37872             if ($attrs[key]) {
37873               $scope.$parent.$watch($attrs[key], function(value) {
37874                 self[key] = $scope[key] = angular.isDefined(value) ? value : $attrs[key];
37875                 if (key === 'minMode' && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) ||
37876                   key === 'maxMode' && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) {
37877                   $scope.datepickerMode = self[key];
37878                 }
37879               });
37880             } else {
37881               self[key] = $scope[key] = datepickerConfig[key] || null;
37882             }
37883           });
37884
37885           $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;
37886           $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
37887
37888           if (angular.isDefined($attrs.initDate)) {
37889             this.activeDate = dateParser.fromTimezone($scope.$parent.$eval($attrs.initDate), ngModelOptions.timezone) || new Date();
37890             $scope.$parent.$watch($attrs.initDate, function(initDate) {
37891               if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
37892                 self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
37893                 self.refreshView();
37894               }
37895             });
37896           } else {
37897             this.activeDate = new Date();
37898           }
37899
37900           $scope.disabled = angular.isDefined($attrs.disabled) || false;
37901           if (angular.isDefined($attrs.ngDisabled)) {
37902             $scope.$parent.$watch($attrs.ngDisabled, function(disabled) {
37903               $scope.disabled = disabled;
37904               self.refreshView();
37905             });
37906           }
37907
37908           $scope.isActive = function(dateObject) {
37909             if (self.compare(dateObject.date, self.activeDate) === 0) {
37910               $scope.activeDateId = dateObject.uid;
37911               return true;
37912             }
37913             return false;
37914           };
37915
37916           this.init = function(ngModelCtrl_) {
37917             ngModelCtrl = ngModelCtrl_;
37918             ngModelOptions = ngModelCtrl_.$options || datepickerConfig.ngModelOptions;
37919
37920             if (ngModelCtrl.$modelValue) {
37921               this.activeDate = ngModelCtrl.$modelValue;
37922             }
37923
37924             ngModelCtrl.$render = function() {
37925               self.render();
37926             };
37927           };
37928
37929           this.render = function() {
37930             if (ngModelCtrl.$viewValue) {
37931               var date = new Date(ngModelCtrl.$viewValue),
37932                   isValid = !isNaN(date);
37933
37934               if (isValid) {
37935                 this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone);
37936               } else if (!$datepickerSuppressError) {
37937                 $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
37938               }
37939             }
37940             this.refreshView();
37941           };
37942
37943           this.refreshView = function() {
37944             if (this.element) {
37945               $scope.selectedDt = null;
37946               this._refreshView();
37947               if ($scope.activeDt) {
37948                 $scope.activeDateId = $scope.activeDt.uid;
37949               }
37950
37951               var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
37952               date = dateParser.fromTimezone(date, ngModelOptions.timezone);
37953               ngModelCtrl.$setValidity('dateDisabled', !date ||
37954                 this.element && !this.isDisabled(date));
37955             }
37956           };
37957
37958           this.createDateObject = function(date, format) {
37959             var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
37960             model = dateParser.fromTimezone(model, ngModelOptions.timezone);
37961             var dt = {
37962               date: date,
37963               label: dateFilter(date, format),
37964               selected: model && this.compare(date, model) === 0,
37965               disabled: this.isDisabled(date),
37966               current: this.compare(date, new Date()) === 0,
37967               customClass: this.customClass(date) || null
37968             };
37969
37970             if (model && this.compare(date, model) === 0) {
37971               $scope.selectedDt = dt;
37972             }
37973
37974             if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {
37975               $scope.activeDt = dt;
37976             }
37977
37978             return dt;
37979           };
37980
37981           this.isDisabled = function(date) {
37982             return $scope.disabled ||
37983               this.minDate && this.compare(date, this.minDate) < 0 ||
37984               this.maxDate && this.compare(date, this.maxDate) > 0 ||
37985               $attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode});
37986           };
37987
37988           this.customClass = function(date) {
37989             return $scope.customClass({date: date, mode: $scope.datepickerMode});
37990           };
37991
37992           // Split array into smaller arrays
37993           this.split = function(arr, size) {
37994             var arrays = [];
37995             while (arr.length > 0) {
37996               arrays.push(arr.splice(0, size));
37997             }
37998             return arrays;
37999           };
38000
38001           $scope.select = function(date) {
38002             if ($scope.datepickerMode === self.minMode) {
38003               var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0);
38004               dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
38005               dt = dateParser.toTimezone(dt, ngModelOptions.timezone);
38006               ngModelCtrl.$setViewValue(dt);
38007               ngModelCtrl.$render();
38008             } else {
38009               self.activeDate = date;
38010               $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1];
38011             }
38012           };
38013
38014           $scope.move = function(direction) {
38015             var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
38016                 month = self.activeDate.getMonth() + direction * (self.step.months || 0);
38017             self.activeDate.setFullYear(year, month, 1);
38018             self.refreshView();
38019           };
38020
38021           $scope.toggleMode = function(direction) {
38022             direction = direction || 1;
38023
38024             if ($scope.datepickerMode === self.maxMode && direction === 1 ||
38025               $scope.datepickerMode === self.minMode && direction === -1) {
38026               return;
38027             }
38028
38029             $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction];
38030 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
38031           };
38032
38033           // Key event mapper
38034           $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };
38035
38036           var focusElement = function() {
38037             self.element[0].focus();
38038           };
38039
38040           // Listen for focus requests from popup directive
38041           $scope.$on('uib:datepicker.focus', focusElement);
38042
38043           $scope.keydown = function(evt) {
38044             var key = $scope.keys[evt.which];
38045
38046             if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
38047               return;
38048             }
38049
38050             evt.preventDefault();
38051             if (!self.shortcutPropagation) {
38052               evt.stopPropagation();
38053             }
38054
38055             if (key === 'enter' || key === 'space') {
38056               if (self.isDisabled(self.activeDate)) {
38057                 return; // do nothing
38058               }
38059               $scope.select(self.activeDate);
38060             } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
38061               $scope.toggleMode(key === 'up' ? 1 : -1);
38062             } else {
38063               self.handleKeyDown(key, evt);
38064               self.refreshView();
38065             }
38066           };
38067 <<<<<<< HEAD
38068
38069           $scope.$on('$destroy', function() {
38070             //Clear all watch listeners on destroy
38071             while (watchListeners.length) {
38072               watchListeners.shift()();
38073             }
38074           });
38075
38076           function setMode(mode) {
38077             $scope.datepickerMode = mode;
38078             $scope.datepickerOptions.datepickerMode = mode;
38079           }
38080 =======
38081 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
38082         }])
38083
38084         .controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
38085           var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
38086
38087           this.step = { months: 1 };
38088           this.element = $element;
38089           function getDaysInMonth(year, month) {
38090             return month === 1 && year % 4 === 0 &&
38091               (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];
38092           }
38093
38094           this.init = function(ctrl) {
38095             angular.extend(ctrl, this);
38096             scope.showWeeks = ctrl.showWeeks;
38097             ctrl.refreshView();
38098           };
38099
38100           this.getDates = function(startDate, n) {
38101             var dates = new Array(n), current = new Date(startDate), i = 0, date;
38102             while (i < n) {
38103               date = new Date(current);
38104               dates[i++] = date;
38105               current.setDate(current.getDate() + 1);
38106             }
38107             return dates;
38108           };
38109
38110           this._refreshView = function() {
38111             var year = this.activeDate.getFullYear(),
38112               month = this.activeDate.getMonth(),
38113               firstDayOfMonth = new Date(this.activeDate);
38114
38115             firstDayOfMonth.setFullYear(year, month, 1);
38116
38117             var difference = this.startingDay - firstDayOfMonth.getDay(),
38118               numDisplayedFromPreviousMonth = difference > 0 ?
38119                 7 - difference : - difference,
38120               firstDate = new Date(firstDayOfMonth);
38121
38122             if (numDisplayedFromPreviousMonth > 0) {
38123               firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
38124             }
38125
38126             // 42 is the number of days on a six-week calendar
38127             var days = this.getDates(firstDate, 42);
38128             for (var i = 0; i < 42; i ++) {
38129               days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {
38130                 secondary: days[i].getMonth() !== month,
38131                 uid: scope.uniqueId + '-' + i
38132               });
38133             }
38134
38135             scope.labels = new Array(7);
38136             for (var j = 0; j < 7; j++) {
38137               scope.labels[j] = {
38138                 abbr: dateFilter(days[j].date, this.formatDayHeader),
38139                 full: dateFilter(days[j].date, 'EEEE')
38140               };
38141             }
38142
38143             scope.title = dateFilter(this.activeDate, this.formatDayTitle);
38144             scope.rows = this.split(days, 7);
38145
38146             if (scope.showWeeks) {
38147               scope.weekNumbers = [];
38148               var thursdayIndex = (4 + 7 - this.startingDay) % 7,
38149                   numWeeks = scope.rows.length;
38150               for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
38151                 scope.weekNumbers.push(
38152                   getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));
38153               }
38154             }
38155           };
38156
38157           this.compare = function(date1, date2) {
38158             var _date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
38159             var _date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
38160             _date1.setFullYear(date1.getFullYear());
38161             _date2.setFullYear(date2.getFullYear());
38162             return _date1 - _date2;
38163           };
38164
38165           function getISO8601WeekNumber(date) {
38166             var checkDate = new Date(date);
38167             checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
38168             var time = checkDate.getTime();
38169             checkDate.setMonth(0); // Compare with Jan 1
38170             checkDate.setDate(1);
38171             return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
38172           }
38173
38174           this.handleKeyDown = function(key, evt) {
38175             var date = this.activeDate.getDate();
38176
38177             if (key === 'left') {
38178               date = date - 1;
38179             } else if (key === 'up') {
38180               date = date - 7;
38181             } else if (key === 'right') {
38182               date = date + 1;
38183             } else if (key === 'down') {
38184               date = date + 7;
38185             } else if (key === 'pageup' || key === 'pagedown') {
38186               var month = this.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);
38187               this.activeDate.setMonth(month, 1);
38188               date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);
38189             } else if (key === 'home') {
38190               date = 1;
38191             } else if (key === 'end') {
38192               date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());
38193             }
38194             this.activeDate.setDate(date);
38195           };
38196         }])
38197
38198         .controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
38199           this.step = { years: 1 };
38200           this.element = $element;
38201
38202           this.init = function(ctrl) {
38203             angular.extend(ctrl, this);
38204             ctrl.refreshView();
38205           };
38206
38207           this._refreshView = function() {
38208             var months = new Array(12),
38209                 year = this.activeDate.getFullYear(),
38210                 date;
38211
38212             for (var i = 0; i < 12; i++) {
38213               date = new Date(this.activeDate);
38214               date.setFullYear(year, i, 1);
38215               months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {
38216                 uid: scope.uniqueId + '-' + i
38217               });
38218             }
38219
38220             scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
38221             scope.rows = this.split(months, 3);
38222           };
38223
38224           this.compare = function(date1, date2) {
38225             var _date1 = new Date(date1.getFullYear(), date1.getMonth());
38226             var _date2 = new Date(date2.getFullYear(), date2.getMonth());
38227             _date1.setFullYear(date1.getFullYear());
38228             _date2.setFullYear(date2.getFullYear());
38229             return _date1 - _date2;
38230           };
38231
38232           this.handleKeyDown = function(key, evt) {
38233             var date = this.activeDate.getMonth();
38234
38235             if (key === 'left') {
38236               date = date - 1;
38237             } else if (key === 'up') {
38238               date = date - 3;
38239             } else if (key === 'right') {
38240               date = date + 1;
38241             } else if (key === 'down') {
38242               date = date + 3;
38243             } else if (key === 'pageup' || key === 'pagedown') {
38244               var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);
38245               this.activeDate.setFullYear(year);
38246             } else if (key === 'home') {
38247               date = 0;
38248             } else if (key === 'end') {
38249               date = 11;
38250             }
38251             this.activeDate.setMonth(date);
38252           };
38253         }])
38254
38255         .controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
38256           var columns, range;
38257           this.element = $element;
38258
38259           function getStartingYear(year) {
38260             return parseInt((year - 1) / range, 10) * range + 1;
38261           }
38262
38263           this.yearpickerInit = function() {
38264             columns = this.yearColumns;
38265             range = this.yearRows * columns;
38266             this.step = { years: range };
38267           };
38268
38269           this._refreshView = function() {
38270             var years = new Array(range), date;
38271
38272             for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) {
38273               date = new Date(this.activeDate);
38274               date.setFullYear(start + i, 0, 1);
38275               years[i] = angular.extend(this.createDateObject(date, this.formatYear), {
38276                 uid: scope.uniqueId + '-' + i
38277               });
38278             }
38279
38280             scope.title = [years[0].label, years[range - 1].label].join(' - ');
38281             scope.rows = this.split(years, columns);
38282             scope.columns = columns;
38283           };
38284
38285           this.compare = function(date1, date2) {
38286             return date1.getFullYear() - date2.getFullYear();
38287           };
38288
38289           this.handleKeyDown = function(key, evt) {
38290             var date = this.activeDate.getFullYear();
38291
38292             if (key === 'left') {
38293               date = date - 1;
38294             } else if (key === 'up') {
38295               date = date - columns;
38296             } else if (key === 'right') {
38297               date = date + 1;
38298             } else if (key === 'down') {
38299               date = date + columns;
38300             } else if (key === 'pageup' || key === 'pagedown') {
38301               date += (key === 'pageup' ? - 1 : 1) * range;
38302             } else if (key === 'home') {
38303               date = getStartingYear(this.activeDate.getFullYear());
38304             } else if (key === 'end') {
38305               date = getStartingYear(this.activeDate.getFullYear()) + range - 1;
38306             }
38307             this.activeDate.setFullYear(date);
38308           };
38309         }])
38310
38311         .directive('uibDatepicker', function() {
38312           return {
38313             replace: true,
38314             templateUrl: function(element, attrs) {
38315               return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';
38316             },
38317             scope: {
38318 <<<<<<< HEAD
38319               datepickerOptions: '=?'
38320 =======
38321               datepickerMode: '=?',
38322               dateDisabled: '&',
38323               customClass: '&',
38324               shortcutPropagation: '&?'
38325 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
38326             },
38327             require: ['uibDatepicker', '^ngModel'],
38328             controller: 'UibDatepickerController',
38329             controllerAs: 'datepicker',
38330             link: function(scope, element, attrs, ctrls) {
38331               var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
38332
38333               datepickerCtrl.init(ngModelCtrl);
38334             }
38335           };
38336         })
38337
38338         .directive('uibDaypicker', function() {
38339           return {
38340             replace: true,
38341             templateUrl: function(element, attrs) {
38342               return attrs.templateUrl || 'uib/template/datepicker/day.html';
38343             },
38344             require: ['^uibDatepicker', 'uibDaypicker'],
38345             controller: 'UibDaypickerController',
38346             link: function(scope, element, attrs, ctrls) {
38347               var datepickerCtrl = ctrls[0],
38348                 daypickerCtrl = ctrls[1];
38349
38350               daypickerCtrl.init(datepickerCtrl);
38351             }
38352           };
38353         })
38354
38355         .directive('uibMonthpicker', function() {
38356           return {
38357             replace: true,
38358             templateUrl: function(element, attrs) {
38359               return attrs.templateUrl || 'uib/template/datepicker/month.html';
38360             },
38361             require: ['^uibDatepicker', 'uibMonthpicker'],
38362             controller: 'UibMonthpickerController',
38363             link: function(scope, element, attrs, ctrls) {
38364               var datepickerCtrl = ctrls[0],
38365                 monthpickerCtrl = ctrls[1];
38366
38367               monthpickerCtrl.init(datepickerCtrl);
38368             }
38369           };
38370         })
38371
38372         .directive('uibYearpicker', function() {
38373           return {
38374             replace: true,
38375             templateUrl: function(element, attrs) {
38376               return attrs.templateUrl || 'uib/template/datepicker/year.html';
38377             },
38378             require: ['^uibDatepicker', 'uibYearpicker'],
38379             controller: 'UibYearpickerController',
38380             link: function(scope, element, attrs, ctrls) {
38381               var ctrl = ctrls[0];
38382               angular.extend(ctrl, ctrls[1]);
38383               ctrl.yearpickerInit();
38384
38385               ctrl.refreshView();
38386             }
38387           };
38388 <<<<<<< HEAD
38389         });
38390
38391         angular.module('ui.bootstrap.position', [])
38392
38393         /**
38394          * A set of utility methods for working with the DOM.
38395          * It is meant to be used where we need to absolute-position elements in
38396          * relation to another element (this is the case for tooltips, popovers,
38397          * typeahead suggestions etc.).
38398          */
38399           .factory('$uibPosition', ['$document', '$window', function($document, $window) {
38400             /**
38401              * Used by scrollbarWidth() function to cache scrollbar's width.
38402              * Do not access this variable directly, use scrollbarWidth() instead.
38403              */
38404             var SCROLLBAR_WIDTH;
38405             /**
38406              * scrollbar on body and html element in IE and Edge overlay
38407              * content and should be considered 0 width.
38408              */
38409             var BODY_SCROLLBAR_WIDTH;
38410             var OVERFLOW_REGEX = {
38411               normal: /(auto|scroll)/,
38412               hidden: /(auto|scroll|hidden)/
38413             };
38414             var PLACEMENT_REGEX = {
38415               auto: /\s?auto?\s?/i,
38416               primary: /^(top|bottom|left|right)$/,
38417               secondary: /^(top|bottom|left|right|center)$/,
38418               vertical: /^(top|bottom)$/
38419             };
38420             var BODY_REGEX = /(HTML|BODY)/;
38421
38422             return {
38423
38424               /**
38425                * Provides a raw DOM element from a jQuery/jQLite element.
38426                *
38427                * @param {element} elem - The element to convert.
38428                *
38429                * @returns {element} A HTML element.
38430                */
38431               getRawNode: function(elem) {
38432                 return elem.nodeName ? elem : elem[0] || elem;
38433               },
38434
38435               /**
38436                * Provides a parsed number for a style property.  Strips
38437                * units and casts invalid numbers to 0.
38438                *
38439                * @param {string} value - The style value to parse.
38440                *
38441                * @returns {number} A valid number.
38442                */
38443               parseStyle: function(value) {
38444                 value = parseFloat(value);
38445                 return isFinite(value) ? value : 0;
38446               },
38447
38448               /**
38449                * Provides the closest positioned ancestor.
38450                *
38451                * @param {element} element - The element to get the offest parent for.
38452                *
38453                * @returns {element} The closest positioned ancestor.
38454                */
38455               offsetParent: function(elem) {
38456                 elem = this.getRawNode(elem);
38457
38458                 var offsetParent = elem.offsetParent || $document[0].documentElement;
38459
38460                 function isStaticPositioned(el) {
38461                   return ($window.getComputedStyle(el).position || 'static') === 'static';
38462                 }
38463
38464                 while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {
38465                   offsetParent = offsetParent.offsetParent;
38466                 }
38467
38468                 return offsetParent || $document[0].documentElement;
38469               },
38470
38471               /**
38472                * Provides the scrollbar width, concept from TWBS measureScrollbar()
38473                * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js
38474                * In IE and Edge, scollbar on body and html element overlay and should
38475                * return a width of 0.
38476                *
38477                * @returns {number} The width of the browser scollbar.
38478                */
38479               scrollbarWidth: function(isBody) {
38480                 if (isBody) {
38481                   if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {
38482                     var bodyElem = $document.find('body');
38483                     bodyElem.addClass('uib-position-body-scrollbar-measure');
38484                     BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;
38485                     BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;
38486                     bodyElem.removeClass('uib-position-body-scrollbar-measure');
38487                   }
38488                   return BODY_SCROLLBAR_WIDTH;
38489                 }
38490
38491                 if (angular.isUndefined(SCROLLBAR_WIDTH)) {
38492                   var scrollElem = angular.element('<div class="uib-position-scrollbar-measure"></div>');
38493                   $document.find('body').append(scrollElem);
38494                   SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;
38495                   SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;
38496                   scrollElem.remove();
38497                 }
38498
38499                 return SCROLLBAR_WIDTH;
38500               },
38501
38502               /**
38503                * Provides the padding required on an element to replace the scrollbar.
38504                *
38505                * @returns {object} An object with the following properties:
38506                *   <ul>
38507                *     <li>**scrollbarWidth**: the width of the scrollbar</li>
38508                *     <li>**widthOverflow**: whether the the width is overflowing</li>
38509                *     <li>**right**: the amount of right padding on the element needed to replace the scrollbar</li>
38510                *     <li>**rightOriginal**: the amount of right padding currently on the element</li>
38511                *     <li>**heightOverflow**: whether the the height is overflowing</li>
38512                *     <li>**bottom**: the amount of bottom padding on the element needed to replace the scrollbar</li>
38513                *     <li>**bottomOriginal**: the amount of bottom padding currently on the element</li>
38514                *   </ul>
38515                */
38516               scrollbarPadding: function(elem) {
38517                 elem = this.getRawNode(elem);
38518
38519                 var elemStyle = $window.getComputedStyle(elem);
38520                 var paddingRight = this.parseStyle(elemStyle.paddingRight);
38521                 var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
38522                 var scrollParent = this.scrollParent(elem, false, true);
38523                 var scrollbarWidth = this.scrollbarWidth(scrollParent, BODY_REGEX.test(scrollParent.tagName));
38524
38525                 return {
38526                   scrollbarWidth: scrollbarWidth,
38527                   widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
38528                   right: paddingRight + scrollbarWidth,
38529                   originalRight: paddingRight,
38530                   heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
38531                   bottom: paddingBottom + scrollbarWidth,
38532                   originalBottom: paddingBottom
38533                  };
38534               },
38535
38536               /**
38537                * Checks to see if the element is scrollable.
38538                *
38539                * @param {element} elem - The element to check.
38540                * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
38541                *   default is false.
38542                *
38543                * @returns {boolean} Whether the element is scrollable.
38544                */
38545               isScrollable: function(elem, includeHidden) {
38546                 elem = this.getRawNode(elem);
38547
38548                 var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
38549                 var elemStyle = $window.getComputedStyle(elem);
38550                 return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
38551               },
38552
38553               /**
38554                * Provides the closest scrollable ancestor.
38555                * A port of the jQuery UI scrollParent method:
38556                * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
38557                *
38558                * @param {element} elem - The element to find the scroll parent of.
38559                * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
38560                *   default is false.
38561                * @param {boolean=} [includeSelf=false] - Should the element being passed be
38562                * included in the scrollable llokup.
38563                *
38564                * @returns {element} A HTML element.
38565                */
38566               scrollParent: function(elem, includeHidden, includeSelf) {
38567                 elem = this.getRawNode(elem);
38568
38569                 var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
38570                 var documentEl = $document[0].documentElement;
38571                 var elemStyle = $window.getComputedStyle(elem);
38572                 if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
38573                   return elem;
38574                 }
38575                 var excludeStatic = elemStyle.position === 'absolute';
38576                 var scrollParent = elem.parentElement || documentEl;
38577
38578                 if (scrollParent === documentEl || elemStyle.position === 'fixed') {
38579                   return documentEl;
38580                 }
38581
38582                 while (scrollParent.parentElement && scrollParent !== documentEl) {
38583                   var spStyle = $window.getComputedStyle(scrollParent);
38584                   if (excludeStatic && spStyle.position !== 'static') {
38585                     excludeStatic = false;
38586                   }
38587
38588                   if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
38589                     break;
38590                   }
38591                   scrollParent = scrollParent.parentElement;
38592                 }
38593
38594                 return scrollParent;
38595               },
38596
38597               /**
38598                * Provides read-only equivalent of jQuery's position function:
38599                * http://api.jquery.com/position/ - distance to closest positioned
38600                * ancestor.  Does not account for margins by default like jQuery position.
38601                *
38602                * @param {element} elem - The element to caclulate the position on.
38603                * @param {boolean=} [includeMargins=false] - Should margins be accounted
38604                * for, default is false.
38605                *
38606                * @returns {object} An object with the following properties:
38607                *   <ul>
38608                *     <li>**width**: the width of the element</li>
38609                *     <li>**height**: the height of the element</li>
38610                *     <li>**top**: distance to top edge of offset parent</li>
38611                *     <li>**left**: distance to left edge of offset parent</li>
38612                *   </ul>
38613                */
38614               position: function(elem, includeMagins) {
38615                 elem = this.getRawNode(elem);
38616
38617                 var elemOffset = this.offset(elem);
38618                 if (includeMagins) {
38619                   var elemStyle = $window.getComputedStyle(elem);
38620                   elemOffset.top -= this.parseStyle(elemStyle.marginTop);
38621                   elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
38622                 }
38623                 var parent = this.offsetParent(elem);
38624                 var parentOffset = {top: 0, left: 0};
38625
38626                 if (parent !== $document[0].documentElement) {
38627                   parentOffset = this.offset(parent);
38628                   parentOffset.top += parent.clientTop - parent.scrollTop;
38629                   parentOffset.left += parent.clientLeft - parent.scrollLeft;
38630                 }
38631
38632                 return {
38633                   width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
38634                   height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
38635                   top: Math.round(elemOffset.top - parentOffset.top),
38636                   left: Math.round(elemOffset.left - parentOffset.left)
38637                 };
38638               },
38639
38640               /**
38641                * Provides read-only equivalent of jQuery's offset function:
38642                * http://api.jquery.com/offset/ - distance to viewport.  Does
38643                * not account for borders, margins, or padding on the body
38644                * element.
38645                *
38646                * @param {element} elem - The element to calculate the offset on.
38647                *
38648                * @returns {object} An object with the following properties:
38649                *   <ul>
38650                *     <li>**width**: the width of the element</li>
38651                *     <li>**height**: the height of the element</li>
38652                *     <li>**top**: distance to top edge of viewport</li>
38653                *     <li>**right**: distance to bottom edge of viewport</li>
38654                *   </ul>
38655                */
38656               offset: function(elem) {
38657                 elem = this.getRawNode(elem);
38658
38659                 var elemBCR = elem.getBoundingClientRect();
38660                 return {
38661                   width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
38662                   height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
38663                   top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
38664                   left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
38665                 };
38666               },
38667
38668               /**
38669                * Provides offset distance to the closest scrollable ancestor
38670                * or viewport.  Accounts for border and scrollbar width.
38671                *
38672                * Right and bottom dimensions represent the distance to the
38673                * respective edge of the viewport element.  If the element
38674                * edge extends beyond the viewport, a negative value will be
38675                * reported.
38676                *
38677                * @param {element} elem - The element to get the viewport offset for.
38678                * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
38679                * of the first scrollable element, default is false.
38680                * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
38681                * be accounted for, default is true.
38682                *
38683                * @returns {object} An object with the following properties:
38684                *   <ul>
38685                *     <li>**top**: distance to the top content edge of viewport element</li>
38686                *     <li>**bottom**: distance to the bottom content edge of viewport element</li>
38687                *     <li>**left**: distance to the left content edge of viewport element</li>
38688                *     <li>**right**: distance to the right content edge of viewport element</li>
38689                *   </ul>
38690                */
38691               viewportOffset: function(elem, useDocument, includePadding) {
38692                 elem = this.getRawNode(elem);
38693                 includePadding = includePadding !== false ? true : false;
38694
38695                 var elemBCR = elem.getBoundingClientRect();
38696                 var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};
38697
38698                 var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
38699                 var offsetParentBCR = offsetParent.getBoundingClientRect();
38700
38701                 offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
38702                 offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
38703                 if (offsetParent === $document[0].documentElement) {
38704                   offsetBCR.top += $window.pageYOffset;
38705                   offsetBCR.left += $window.pageXOffset;
38706                 }
38707                 offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
38708                 offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;
38709
38710                 if (includePadding) {
38711                   var offsetParentStyle = $window.getComputedStyle(offsetParent);
38712                   offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
38713                   offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
38714                   offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
38715                   offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
38716                 }
38717
38718                 return {
38719                   top: Math.round(elemBCR.top - offsetBCR.top),
38720                   bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
38721                   left: Math.round(elemBCR.left - offsetBCR.left),
38722                   right: Math.round(offsetBCR.right - elemBCR.right)
38723                 };
38724               },
38725
38726               /**
38727                * Provides an array of placement values parsed from a placement string.
38728                * Along with the 'auto' indicator, supported placement strings are:
38729                *   <ul>
38730                *     <li>top: element on top, horizontally centered on host element.</li>
38731                *     <li>top-left: element on top, left edge aligned with host element left edge.</li>
38732                *     <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>
38733                *     <li>bottom: element on bottom, horizontally centered on host element.</li>
38734                *     <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>
38735                *     <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>
38736                *     <li>left: element on left, vertically centered on host element.</li>
38737                *     <li>left-top: element on left, top edge aligned with host element top edge.</li>
38738                *     <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>
38739                *     <li>right: element on right, vertically centered on host element.</li>
38740                *     <li>right-top: element on right, top edge aligned with host element top edge.</li>
38741                *     <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>
38742                *   </ul>
38743                * A placement string with an 'auto' indicator is expected to be
38744                * space separated from the placement, i.e: 'auto bottom-left'  If
38745                * the primary and secondary placement values do not match 'top,
38746                * bottom, left, right' then 'top' will be the primary placement and
38747                * 'center' will be the secondary placement.  If 'auto' is passed, true
38748                * will be returned as the 3rd value of the array.
38749                *
38750                * @param {string} placement - The placement string to parse.
38751                *
38752                * @returns {array} An array with the following values
38753                * <ul>
38754                *   <li>**[0]**: The primary placement.</li>
38755                *   <li>**[1]**: The secondary placement.</li>
38756                *   <li>**[2]**: If auto is passed: true, else undefined.</li>
38757                * </ul>
38758                */
38759               parsePlacement: function(placement) {
38760                 var autoPlace = PLACEMENT_REGEX.auto.test(placement);
38761                 if (autoPlace) {
38762                   placement = placement.replace(PLACEMENT_REGEX.auto, '');
38763                 }
38764
38765                 placement = placement.split('-');
38766
38767                 placement[0] = placement[0] || 'top';
38768                 if (!PLACEMENT_REGEX.primary.test(placement[0])) {
38769                   placement[0] = 'top';
38770                 }
38771
38772                 placement[1] = placement[1] || 'center';
38773                 if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
38774                   placement[1] = 'center';
38775                 }
38776
38777                 if (autoPlace) {
38778                   placement[2] = true;
38779                 } else {
38780                   placement[2] = false;
38781                 }
38782
38783                 return placement;
38784               },
38785
38786               /**
38787                * Provides coordinates for an element to be positioned relative to
38788                * another element.  Passing 'auto' as part of the placement parameter
38789                * will enable smart placement - where the element fits. i.e:
38790                * 'auto left-top' will check to see if there is enough space to the left
38791                * of the hostElem to fit the targetElem, if not place right (same for secondary
38792                * top placement).  Available space is calculated using the viewportOffset
38793                * function.
38794                *
38795                * @param {element} hostElem - The element to position against.
38796                * @param {element} targetElem - The element to position.
38797                * @param {string=} [placement=top] - The placement for the targetElem,
38798                *   default is 'top'. 'center' is assumed as secondary placement for
38799                *   'top', 'left', 'right', and 'bottom' placements.  Available placements are:
38800                *   <ul>
38801                *     <li>top</li>
38802                *     <li>top-right</li>
38803                *     <li>top-left</li>
38804                *     <li>bottom</li>
38805                *     <li>bottom-left</li>
38806                *     <li>bottom-right</li>
38807                *     <li>left</li>
38808                *     <li>left-top</li>
38809                *     <li>left-bottom</li>
38810                *     <li>right</li>
38811                *     <li>right-top</li>
38812                *     <li>right-bottom</li>
38813                *   </ul>
38814                * @param {boolean=} [appendToBody=false] - Should the top and left values returned
38815                *   be calculated from the body element, default is false.
38816                *
38817                * @returns {object} An object with the following properties:
38818                *   <ul>
38819                *     <li>**top**: Value for targetElem top.</li>
38820                *     <li>**left**: Value for targetElem left.</li>
38821                *     <li>**placement**: The resolved placement.</li>
38822                *   </ul>
38823                */
38824               positionElements: function(hostElem, targetElem, placement, appendToBody) {
38825                 hostElem = this.getRawNode(hostElem);
38826                 targetElem = this.getRawNode(targetElem);
38827
38828                 // need to read from prop to support tests.
38829                 var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
38830                 var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');
38831
38832                 placement = this.parsePlacement(placement);
38833
38834                 var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
38835                 var targetElemPos = {top: 0, left: 0, placement: ''};
38836
38837                 if (placement[2]) {
38838                   var viewportOffset = this.viewportOffset(hostElem, appendToBody);
38839
38840                   var targetElemStyle = $window.getComputedStyle(targetElem);
38841                   var adjustedSize = {
38842                     width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
38843                     height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
38844                   };
38845
38846                   placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
38847                                  placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
38848                                  placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
38849                                  placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
38850                                  placement[0];
38851
38852                   placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
38853                                  placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
38854                                  placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
38855                                  placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
38856                                  placement[1];
38857
38858                   if (placement[1] === 'center') {
38859                     if (PLACEMENT_REGEX.vertical.test(placement[0])) {
38860                       var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
38861                       if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
38862                         placement[1] = 'left';
38863                       } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
38864                         placement[1] = 'right';
38865                       }
38866                     } else {
38867                       var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
38868                       if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
38869                         placement[1] = 'top';
38870                       } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
38871                         placement[1] = 'bottom';
38872                       }
38873                     }
38874                   }
38875                 }
38876
38877                 switch (placement[0]) {
38878                   case 'top':
38879                     targetElemPos.top = hostElemPos.top - targetHeight;
38880                     break;
38881                   case 'bottom':
38882                     targetElemPos.top = hostElemPos.top + hostElemPos.height;
38883                     break;
38884                   case 'left':
38885                     targetElemPos.left = hostElemPos.left - targetWidth;
38886                     break;
38887                   case 'right':
38888                     targetElemPos.left = hostElemPos.left + hostElemPos.width;
38889                     break;
38890                 }
38891
38892                 switch (placement[1]) {
38893                   case 'top':
38894                     targetElemPos.top = hostElemPos.top;
38895                     break;
38896                   case 'bottom':
38897                     targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
38898                     break;
38899                   case 'left':
38900                     targetElemPos.left = hostElemPos.left;
38901                     break;
38902                   case 'right':
38903                     targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
38904                     break;
38905                   case 'center':
38906                     if (PLACEMENT_REGEX.vertical.test(placement[0])) {
38907                       targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
38908                     } else {
38909                       targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
38910                     }
38911                     break;
38912                 }
38913
38914                 targetElemPos.top = Math.round(targetElemPos.top);
38915                 targetElemPos.left = Math.round(targetElemPos.left);
38916                 targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];
38917
38918                 return targetElemPos;
38919               },
38920
38921               /**
38922               * Provides a way for positioning tooltip & dropdown
38923               * arrows when using placement options beyond the standard
38924               * left, right, top, or bottom.
38925               *
38926               * @param {element} elem - The tooltip/dropdown element.
38927               * @param {string} placement - The placement for the elem.
38928               */
38929               positionArrow: function(elem, placement) {
38930                 elem = this.getRawNode(elem);
38931
38932                 var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
38933                 if (!innerElem) {
38934                   return;
38935                 }
38936
38937                 var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');
38938
38939                 var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
38940                 if (!arrowElem) {
38941                   return;
38942                 }
38943
38944                 var arrowCss = {
38945                   top: '',
38946                   bottom: '',
38947                   left: '',
38948                   right: ''
38949                 };
38950
38951                 placement = this.parsePlacement(placement);
38952                 if (placement[1] === 'center') {
38953                   // no adjustment necessary - just reset styles
38954                   angular.element(arrowElem).css(arrowCss);
38955                   return;
38956                 }
38957
38958                 var borderProp = 'border-' + placement[0] + '-width';
38959                 var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];
38960
38961                 var borderRadiusProp = 'border-';
38962                 if (PLACEMENT_REGEX.vertical.test(placement[0])) {
38963                   borderRadiusProp += placement[0] + '-' + placement[1];
38964                 } else {
38965                   borderRadiusProp += placement[1] + '-' + placement[0];
38966                 }
38967                 borderRadiusProp += '-radius';
38968                 var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];
38969
38970                 switch (placement[0]) {
38971                   case 'top':
38972                     arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
38973                     break;
38974                   case 'bottom':
38975                     arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
38976                     break;
38977                   case 'left':
38978                     arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
38979                     break;
38980                   case 'right':
38981                     arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
38982                     break;
38983                 }
38984
38985                 arrowCss[placement[1]] = borderRadius;
38986
38987                 angular.element(arrowElem).css(arrowCss);
38988               }
38989             };
38990           }]);
38991
38992         angular.module('ui.bootstrap.datepickerPopup', ['ui.bootstrap.datepicker', 'ui.bootstrap.position'])
38993
38994         .value('$datepickerPopupLiteralWarning', true)
38995
38996         .constant('uibDatepickerPopupConfig', {
38997           altInputFormats: [],
38998           appendToBody: false,
38999           clearText: 'Clear',
39000           closeOnDateSelection: true,
39001           closeText: 'Done',
39002           currentText: 'Today',
39003           datepickerPopup: 'yyyy-MM-dd',
39004           datepickerPopupTemplateUrl: 'uib/template/datepickerPopup/popup.html',
39005           datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',
39006           html5Types: {
39007             date: 'yyyy-MM-dd',
39008             'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
39009             'month': 'yyyy-MM'
39010           },
39011           onOpenFocus: true,
39012           showButtonBar: true,
39013           placement: 'auto bottom-left'
39014         })
39015
39016         .controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
39017         function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
39018           var cache = {},
39019             isHtml5DateInput = false;
39020           var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
39021             datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
39022             ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [],
39023             timezone;
39024
39025           this.init = function(_ngModel_) {
39026             ngModel = _ngModel_;
39027             ngModelOptions = _ngModel_.$options;
39028             closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
39029               $scope.$parent.$eval($attrs.closeOnDateSelection) :
39030               datepickerPopupConfig.closeOnDateSelection;
39031             appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
39032               $scope.$parent.$eval($attrs.datepickerAppendToBody) :
39033               datepickerPopupConfig.appendToBody;
39034             onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
39035               $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
39036             datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
39037               $attrs.datepickerPopupTemplateUrl :
39038               datepickerPopupConfig.datepickerPopupTemplateUrl;
39039             datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
39040               $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
39041             altInputFormats = angular.isDefined($attrs.altInputFormats) ?
39042               $scope.$parent.$eval($attrs.altInputFormats) :
39043               datepickerPopupConfig.altInputFormats;
39044
39045             $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
39046               $scope.$parent.$eval($attrs.showButtonBar) :
39047               datepickerPopupConfig.showButtonBar;
39048
39049             if (datepickerPopupConfig.html5Types[$attrs.type]) {
39050               dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
39051               isHtml5DateInput = true;
39052             } else {
39053               dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
39054               $attrs.$observe('uibDatepickerPopup', function(value, oldValue) {
39055                 var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
39056                 // Invalidate the $modelValue to ensure that formatters re-run
39057                 // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
39058                 if (newDateFormat !== dateFormat) {
39059                   dateFormat = newDateFormat;
39060                   ngModel.$modelValue = null;
39061
39062                   if (!dateFormat) {
39063                     throw new Error('uibDatepickerPopup must have a date format specified.');
39064                   }
39065                 }
39066               });
39067             }
39068
39069             if (!dateFormat) {
39070               throw new Error('uibDatepickerPopup must have a date format specified.');
39071             }
39072
39073             if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
39074               throw new Error('HTML5 date input types do not support custom formats.');
39075             }
39076
39077             // popup element used to display calendar
39078             popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
39079             if (ngModelOptions) {
39080               timezone = ngModelOptions.timezone;
39081               $scope.ngModelOptions = angular.copy(ngModelOptions);
39082               $scope.ngModelOptions.timezone = null;
39083               if ($scope.ngModelOptions.updateOnDefault === true) {
39084                 $scope.ngModelOptions.updateOn = $scope.ngModelOptions.updateOn ?
39085                   $scope.ngModelOptions.updateOn + ' default' : 'default';
39086               }
39087
39088               popupEl.attr('ng-model-options', 'ngModelOptions');
39089             } else {
39090               timezone = null;
39091             }
39092
39093             popupEl.attr({
39094               'ng-model': 'date',
39095               'ng-change': 'dateSelection(date)',
39096               'template-url': datepickerPopupTemplateUrl
39097             });
39098
39099             // datepicker element
39100             datepickerEl = angular.element(popupEl.children()[0]);
39101             datepickerEl.attr('template-url', datepickerTemplateUrl);
39102
39103             if (!$scope.datepickerOptions) {
39104               $scope.datepickerOptions = {};
39105             }
39106
39107             if (isHtml5DateInput) {
39108               if ($attrs.type === 'month') {
39109                 $scope.datepickerOptions.datepickerMode = 'month';
39110                 $scope.datepickerOptions.minMode = 'month';
39111               }
39112             }
39113
39114             datepickerEl.attr('datepicker-options', 'datepickerOptions');
39115
39116             if (!isHtml5DateInput) {
39117               // Internal API to maintain the correct ng-invalid-[key] class
39118               ngModel.$$parserName = 'date';
39119               ngModel.$validators.date = validator;
39120               ngModel.$parsers.unshift(parseDate);
39121               ngModel.$formatters.push(function(value) {
39122                 if (ngModel.$isEmpty(value)) {
39123                   $scope.date = value;
39124                   return value;
39125                 }
39126
39127                 if (angular.isNumber(value)) {
39128                   value = new Date(value);
39129                 }
39130
39131                 $scope.date = dateParser.fromTimezone(value, timezone);
39132
39133                 return dateParser.filter($scope.date, dateFormat);
39134               });
39135             } else {
39136               ngModel.$formatters.push(function(value) {
39137                 $scope.date = dateParser.fromTimezone(value, timezone);
39138                 return value;
39139               });
39140             }
39141
39142             // Detect changes in the view from the text box
39143             ngModel.$viewChangeListeners.push(function() {
39144               $scope.date = parseDateString(ngModel.$viewValue);
39145             });
39146
39147             $element.on('keydown', inputKeydownBind);
39148
39149             $popup = $compile(popupEl)($scope);
39150             // Prevent jQuery cache memory leak (template is now redundant after linking)
39151             popupEl.remove();
39152
39153             if (appendToBody) {
39154               $document.find('body').append($popup);
39155             } else {
39156               $element.after($popup);
39157             }
39158
39159             $scope.$on('$destroy', function() {
39160               if ($scope.isOpen === true) {
39161                 if (!$rootScope.$$phase) {
39162                   $scope.$apply(function() {
39163                     $scope.isOpen = false;
39164                   });
39165                 }
39166               }
39167
39168               $popup.remove();
39169               $element.off('keydown', inputKeydownBind);
39170               $document.off('click', documentClickBind);
39171               if (scrollParentEl) {
39172                 scrollParentEl.off('scroll', positionPopup);
39173               }
39174               angular.element($window).off('resize', positionPopup);
39175
39176               //Clear all watch listeners on destroy
39177               while (watchListeners.length) {
39178                 watchListeners.shift()();
39179               }
39180             });
39181           };
39182
39183           $scope.getText = function(key) {
39184             return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
39185           };
39186
39187           $scope.isDisabled = function(date) {
39188             if (date === 'today') {
39189               date = dateParser.fromTimezone(new Date(), timezone);
39190             }
39191
39192             var dates = {};
39193             angular.forEach(['minDate', 'maxDate'], function(key) {
39194               if (!$scope.datepickerOptions[key]) {
39195                 dates[key] = null;
39196               } else if (angular.isDate($scope.datepickerOptions[key])) {
39197                 dates[key] = dateParser.fromTimezone(new Date($scope.datepickerOptions[key]), timezone);
39198               } else {
39199                 if ($datepickerPopupLiteralWarning) {
39200                   $log.warn('Literal date support has been deprecated, please switch to date object usage');
39201                 }
39202
39203                 dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
39204               }
39205             });
39206
39207             return $scope.datepickerOptions &&
39208               dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
39209               dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
39210           };
39211
39212           $scope.compare = function(date1, date2) {
39213             return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
39214           };
39215
39216           // Inner change
39217           $scope.dateSelection = function(dt) {
39218             if (angular.isDefined(dt)) {
39219               $scope.date = dt;
39220             }
39221             var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
39222             $element.val(date);
39223             ngModel.$setViewValue(date);
39224
39225             if (closeOnDateSelection) {
39226               $scope.isOpen = false;
39227               $element[0].focus();
39228             }
39229           };
39230
39231           $scope.keydown = function(evt) {
39232             if (evt.which === 27) {
39233               evt.stopPropagation();
39234               $scope.isOpen = false;
39235               $element[0].focus();
39236             }
39237           };
39238
39239           $scope.select = function(date, evt) {
39240             evt.stopPropagation();
39241
39242             if (date === 'today') {
39243               var today = new Date();
39244               if (angular.isDate($scope.date)) {
39245                 date = new Date($scope.date);
39246                 date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
39247               } else {
39248                 date = new Date(today.setHours(0, 0, 0, 0));
39249               }
39250             }
39251             $scope.dateSelection(date);
39252           };
39253
39254           $scope.close = function(evt) {
39255             evt.stopPropagation();
39256
39257             $scope.isOpen = false;
39258             $element[0].focus();
39259           };
39260
39261           $scope.disabled = angular.isDefined($attrs.disabled) || false;
39262           if ($attrs.ngDisabled) {
39263             watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {
39264               $scope.disabled = disabled;
39265             }));
39266           }
39267
39268           $scope.$watch('isOpen', function(value) {
39269             if (value) {
39270               if (!$scope.disabled) {
39271                 $timeout(function() {
39272                   positionPopup();
39273
39274                   if (onOpenFocus) {
39275                     $scope.$broadcast('uib:datepicker.focus');
39276                   }
39277
39278                   $document.on('click', documentClickBind);
39279
39280                   var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
39281                   if (appendToBody || $position.parsePlacement(placement)[2]) {
39282                     scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
39283                     if (scrollParentEl) {
39284                       scrollParentEl.on('scroll', positionPopup);
39285                     }
39286                   } else {
39287                     scrollParentEl = null;
39288                   }
39289
39290                   angular.element($window).on('resize', positionPopup);
39291                 }, 0, false);
39292               } else {
39293                 $scope.isOpen = false;
39294               }
39295             } else {
39296               $document.off('click', documentClickBind);
39297               if (scrollParentEl) {
39298                 scrollParentEl.off('scroll', positionPopup);
39299               }
39300               angular.element($window).off('resize', positionPopup);
39301             }
39302           });
39303
39304           function cameltoDash(string) {
39305             return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
39306           }
39307
39308           function parseDateString(viewValue) {
39309             var date = dateParser.parse(viewValue, dateFormat, $scope.date);
39310             if (isNaN(date)) {
39311               for (var i = 0; i < altInputFormats.length; i++) {
39312                 date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
39313                 if (!isNaN(date)) {
39314                   return date;
39315                 }
39316               }
39317             }
39318             return date;
39319           }
39320
39321           function parseDate(viewValue) {
39322             if (angular.isNumber(viewValue)) {
39323               // presumably timestamp to date object
39324               viewValue = new Date(viewValue);
39325             }
39326
39327             if (!viewValue) {
39328               return null;
39329             }
39330
39331             if (angular.isDate(viewValue) && !isNaN(viewValue)) {
39332               return viewValue;
39333             }
39334
39335             if (angular.isString(viewValue)) {
39336               var date = parseDateString(viewValue);
39337               if (!isNaN(date)) {
39338                 return dateParser.toTimezone(date, timezone);
39339               }
39340             }
39341
39342             return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined;
39343           }
39344
39345           function validator(modelValue, viewValue) {
39346             var value = modelValue || viewValue;
39347
39348             if (!$attrs.ngRequired && !value) {
39349               return true;
39350             }
39351
39352             if (angular.isNumber(value)) {
39353               value = new Date(value);
39354             }
39355
39356             if (!value) {
39357               return true;
39358             }
39359
39360             if (angular.isDate(value) && !isNaN(value)) {
39361               return true;
39362             }
39363
39364             if (angular.isString(value)) {
39365               return !isNaN(parseDateString(viewValue));
39366             }
39367
39368             return false;
39369           }
39370
39371           function documentClickBind(event) {
39372             if (!$scope.isOpen && $scope.disabled) {
39373               return;
39374             }
39375
39376             var popup = $popup[0];
39377             var dpContainsTarget = $element[0].contains(event.target);
39378             // The popup node may not be an element node
39379             // In some browsers (IE) only element nodes have the 'contains' function
39380             var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
39381             if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
39382               $scope.$apply(function() {
39383                 $scope.isOpen = false;
39384               });
39385             }
39386           }
39387
39388           function inputKeydownBind(evt) {
39389             if (evt.which === 27 && $scope.isOpen) {
39390               evt.preventDefault();
39391               evt.stopPropagation();
39392               $scope.$apply(function() {
39393                 $scope.isOpen = false;
39394               });
39395               $element[0].focus();
39396             } else if (evt.which === 40 && !$scope.isOpen) {
39397               evt.preventDefault();
39398               evt.stopPropagation();
39399               $scope.$apply(function() {
39400                 $scope.isOpen = true;
39401               });
39402             }
39403           }
39404
39405           function positionPopup() {
39406             if ($scope.isOpen) {
39407               var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
39408               var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
39409               var position = $position.positionElements($element, dpElement, placement, appendToBody);
39410               dpElement.css({top: position.top + 'px', left: position.left + 'px'});
39411               if (dpElement.hasClass('uib-position-measure')) {
39412                 dpElement.removeClass('uib-position-measure');
39413               }
39414             }
39415           }
39416
39417           $scope.$on('uib:datepicker.mode', function() {
39418             $timeout(positionPopup, 0, false);
39419           });
39420         }])
39421 =======
39422         })
39423
39424         .constant('uibDatepickerPopupConfig', {
39425           datepickerPopup: 'yyyy-MM-dd',
39426           datepickerPopupTemplateUrl: 'uib/template/datepicker/popup.html',
39427           datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',
39428           html5Types: {
39429             date: 'yyyy-MM-dd',
39430             'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
39431             'month': 'yyyy-MM'
39432           },
39433           currentText: 'Today',
39434           clearText: 'Clear',
39435           closeText: 'Done',
39436           closeOnDateSelection: true,
39437           appendToBody: false,
39438           showButtonBar: true,
39439           onOpenFocus: true,
39440           altInputFormats: []
39441         })
39442
39443         .controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig',
39444         function(scope, element, attrs, $compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig) {
39445           var self = this;
39446           var cache = {},
39447             isHtml5DateInput = false;
39448           var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
39449             datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl,
39450             ngModel, ngModelOptions, $popup, altInputFormats;
39451
39452           scope.watchData = {};
39453
39454           this.init = function(_ngModel_) {
39455             ngModel = _ngModel_;
39456             ngModelOptions = _ngModel_.$options || datepickerConfig.ngModelOptions;
39457             closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection;
39458             appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;
39459             onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
39460             datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl;
39461             datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
39462             altInputFormats = angular.isDefined(attrs.altInputFormats) ? scope.$parent.$eval(attrs.altInputFormats) : datepickerPopupConfig.altInputFormats;
39463
39464             scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;
39465
39466             if (datepickerPopupConfig.html5Types[attrs.type]) {
39467               dateFormat = datepickerPopupConfig.html5Types[attrs.type];
39468               isHtml5DateInput = true;
39469             } else {
39470               dateFormat = attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
39471               attrs.$observe('uibDatepickerPopup', function(value, oldValue) {
39472                   var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
39473                   // Invalidate the $modelValue to ensure that formatters re-run
39474                   // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
39475                   if (newDateFormat !== dateFormat) {
39476                     dateFormat = newDateFormat;
39477                     ngModel.$modelValue = null;
39478
39479                     if (!dateFormat) {
39480                       throw new Error('uibDatepickerPopup must have a date format specified.');
39481                     }
39482                   }
39483               });
39484             }
39485
39486             if (!dateFormat) {
39487               throw new Error('uibDatepickerPopup must have a date format specified.');
39488             }
39489
39490             if (isHtml5DateInput && attrs.uibDatepickerPopup) {
39491               throw new Error('HTML5 date input types do not support custom formats.');
39492             }
39493
39494             // popup element used to display calendar
39495             popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
39496             scope.ngModelOptions = angular.copy(ngModelOptions);
39497             scope.ngModelOptions.timezone = null;
39498             popupEl.attr({
39499               'ng-model': 'date',
39500               'ng-model-options': 'ngModelOptions',
39501               'ng-change': 'dateSelection(date)',
39502               'template-url': datepickerPopupTemplateUrl
39503             });
39504
39505             // datepicker element
39506             datepickerEl = angular.element(popupEl.children()[0]);
39507             datepickerEl.attr('template-url', datepickerTemplateUrl);
39508
39509             if (isHtml5DateInput) {
39510               if (attrs.type === 'month') {
39511                 datepickerEl.attr('datepicker-mode', '"month"');
39512                 datepickerEl.attr('min-mode', 'month');
39513               }
39514             }
39515
39516             if (attrs.datepickerOptions) {
39517               var options = scope.$parent.$eval(attrs.datepickerOptions);
39518               if (options && options.initDate) {
39519                 scope.initDate = dateParser.fromTimezone(options.initDate, ngModelOptions.timezone);
39520                 datepickerEl.attr('init-date', 'initDate');
39521                 delete options.initDate;
39522               }
39523               angular.forEach(options, function(value, option) {
39524                 datepickerEl.attr(cameltoDash(option), value);
39525               });
39526             }
39527
39528             angular.forEach(['minMode', 'maxMode'], function(key) {
39529               if (attrs[key]) {
39530                 scope.$parent.$watch(function() { return attrs[key]; }, function(value) {
39531                   scope.watchData[key] = value;
39532                 });
39533                 datepickerEl.attr(cameltoDash(key), 'watchData.' + key);
39534               }
39535             });
39536
39537             angular.forEach(['datepickerMode', 'shortcutPropagation'], function(key) {
39538               if (attrs[key]) {
39539                 var getAttribute = $parse(attrs[key]);
39540                 var propConfig = {
39541                   get: function() {
39542                     return getAttribute(scope.$parent);
39543                   }
39544                 };
39545
39546                 datepickerEl.attr(cameltoDash(key), 'watchData.' + key);
39547
39548                 // Propagate changes from datepicker to outside
39549                 if (key === 'datepickerMode') {
39550                   var setAttribute = getAttribute.assign;
39551                   propConfig.set = function(v) {
39552                     setAttribute(scope.$parent, v);
39553                   };
39554                 }
39555
39556                 Object.defineProperty(scope.watchData, key, propConfig);
39557               }
39558             });
39559
39560             angular.forEach(['minDate', 'maxDate', 'initDate'], function(key) {
39561               if (attrs[key]) {
39562                 var getAttribute = $parse(attrs[key]);
39563
39564                 scope.$parent.$watch(getAttribute, function(value) {
39565                   if (key === 'minDate' || key === 'maxDate') {
39566                     cache[key] = angular.isDate(value) ? dateParser.fromTimezone(new Date(value), ngModelOptions.timezone) : new Date(dateFilter(value, 'medium'));
39567                   }
39568
39569                   scope.watchData[key] = cache[key] || dateParser.fromTimezone(new Date(value), ngModelOptions.timezone);
39570                 });
39571
39572                 datepickerEl.attr(cameltoDash(key), 'watchData.' + key);
39573               }
39574             });
39575
39576             if (attrs.dateDisabled) {
39577               datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');
39578             }
39579
39580             angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle', 'showWeeks', 'startingDay', 'yearRows', 'yearColumns'], function(key) {
39581               if (angular.isDefined(attrs[key])) {
39582                 datepickerEl.attr(cameltoDash(key), attrs[key]);
39583               }
39584             });
39585
39586             if (attrs.customClass) {
39587               datepickerEl.attr('custom-class', 'customClass({ date: date, mode: mode })');
39588             }
39589
39590             if (!isHtml5DateInput) {
39591               // Internal API to maintain the correct ng-invalid-[key] class
39592               ngModel.$$parserName = 'date';
39593               ngModel.$validators.date = validator;
39594               ngModel.$parsers.unshift(parseDate);
39595               ngModel.$formatters.push(function(value) {
39596                 if (ngModel.$isEmpty(value)) {
39597                   scope.date = value;
39598                   return value;
39599                 }
39600                 scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);
39601                 return dateFilter(scope.date, dateFormat);
39602               });
39603             } else {
39604               ngModel.$formatters.push(function(value) {
39605                 scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);
39606                 return value;
39607               });
39608             }
39609
39610             // Detect changes in the view from the text box
39611             ngModel.$viewChangeListeners.push(function() {
39612               scope.date = parseDateString(ngModel.$viewValue);
39613             });
39614
39615             element.bind('keydown', inputKeydownBind);
39616
39617             $popup = $compile(popupEl)(scope);
39618             // Prevent jQuery cache memory leak (template is now redundant after linking)
39619             popupEl.remove();
39620
39621             if (appendToBody) {
39622               $document.find('body').append($popup);
39623             } else {
39624               element.after($popup);
39625             }
39626
39627             scope.$on('$destroy', function() {
39628               if (scope.isOpen === true) {
39629                 if (!$rootScope.$$phase) {
39630                   scope.$apply(function() {
39631                     scope.isOpen = false;
39632                   });
39633                 }
39634               }
39635
39636               $popup.remove();
39637               element.unbind('keydown', inputKeydownBind);
39638               $document.unbind('click', documentClickBind);
39639             });
39640           };
39641
39642           scope.getText = function(key) {
39643             return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
39644           };
39645
39646           scope.isDisabled = function(date) {
39647             if (date === 'today') {
39648               date = new Date();
39649             }
39650
39651             return scope.watchData.minDate && scope.compare(date, cache.minDate) < 0 ||
39652               scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0;
39653           };
39654
39655           scope.compare = function(date1, date2) {
39656             return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
39657           };
39658
39659           // Inner change
39660           scope.dateSelection = function(dt) {
39661             if (angular.isDefined(dt)) {
39662               scope.date = dt;
39663             }
39664             var date = scope.date ? dateFilter(scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
39665             element.val(date);
39666             ngModel.$setViewValue(date);
39667
39668             if (closeOnDateSelection) {
39669               scope.isOpen = false;
39670               element[0].focus();
39671             }
39672           };
39673
39674           scope.keydown = function(evt) {
39675             if (evt.which === 27) {
39676               evt.stopPropagation();
39677               scope.isOpen = false;
39678               element[0].focus();
39679             }
39680           };
39681
39682           scope.select = function(date) {
39683             if (date === 'today') {
39684               var today = new Date();
39685               if (angular.isDate(scope.date)) {
39686                 date = new Date(scope.date);
39687                 date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
39688               } else {
39689                 date = new Date(today.setHours(0, 0, 0, 0));
39690               }
39691             }
39692             scope.dateSelection(date);
39693           };
39694
39695           scope.close = function() {
39696             scope.isOpen = false;
39697             element[0].focus();
39698           };
39699
39700           scope.disabled = angular.isDefined(attrs.disabled) || false;
39701           if (attrs.ngDisabled) {
39702             scope.$parent.$watch($parse(attrs.ngDisabled), function(disabled) {
39703               scope.disabled = disabled;
39704             });
39705           }
39706
39707           scope.$watch('isOpen', function(value) {
39708             if (value) {
39709               if (!scope.disabled) {
39710                 scope.position = appendToBody ? $position.offset(element) : $position.position(element);
39711                 scope.position.top = scope.position.top + element.prop('offsetHeight');
39712
39713                 $timeout(function() {
39714                   if (onOpenFocus) {
39715                     scope.$broadcast('uib:datepicker.focus');
39716                   }
39717                   $document.bind('click', documentClickBind);
39718                 }, 0, false);
39719               } else {
39720                 scope.isOpen = false;
39721               }
39722             } else {
39723               $document.unbind('click', documentClickBind);
39724             }
39725           });
39726
39727           function cameltoDash(string) {
39728             return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
39729           }
39730
39731           function parseDateString(viewValue) {
39732             var date = dateParser.parse(viewValue, dateFormat, scope.date);
39733             if (isNaN(date)) {
39734               for (var i = 0; i < altInputFormats.length; i++) {
39735                 date = dateParser.parse(viewValue, altInputFormats[i], scope.date);
39736                 if (!isNaN(date)) {
39737                   return date;
39738                 }
39739               }
39740             }
39741             return date;
39742           }
39743
39744           function parseDate(viewValue) {
39745             if (angular.isNumber(viewValue)) {
39746               // presumably timestamp to date object
39747               viewValue = new Date(viewValue);
39748             }
39749
39750             if (!viewValue) {
39751               return null;
39752             }
39753
39754             if (angular.isDate(viewValue) && !isNaN(viewValue)) {
39755               return viewValue;
39756             }
39757
39758             if (angular.isString(viewValue)) {
39759               var date = parseDateString(viewValue);
39760               if (!isNaN(date)) {
39761                 return dateParser.toTimezone(date, ngModelOptions.timezone);
39762               }
39763             }
39764
39765             return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined;
39766           }
39767
39768           function validator(modelValue, viewValue) {
39769             var value = modelValue || viewValue;
39770
39771             if (!attrs.ngRequired && !value) {
39772               return true;
39773             }
39774
39775             if (angular.isNumber(value)) {
39776               value = new Date(value);
39777             }
39778
39779             if (!value) {
39780               return true;
39781             }
39782
39783             if (angular.isDate(value) && !isNaN(value)) {
39784               return true;
39785             }
39786
39787             if (angular.isString(value)) {
39788               return !isNaN(parseDateString(viewValue));
39789             }
39790
39791             return false;
39792           }
39793
39794           function documentClickBind(event) {
39795             if (!scope.isOpen && scope.disabled) {
39796               return;
39797             }
39798
39799             var popup = $popup[0];
39800             var dpContainsTarget = element[0].contains(event.target);
39801             // The popup node may not be an element node
39802             // In some browsers (IE) only element nodes have the 'contains' function
39803             var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
39804             if (scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
39805               scope.$apply(function() {
39806                 scope.isOpen = false;
39807               });
39808             }
39809           }
39810
39811           function inputKeydownBind(evt) {
39812             if (evt.which === 27 && scope.isOpen) {
39813               evt.preventDefault();
39814               evt.stopPropagation();
39815               scope.$apply(function() {
39816                 scope.isOpen = false;
39817               });
39818               element[0].focus();
39819             } else if (evt.which === 40 && !scope.isOpen) {
39820               evt.preventDefault();
39821               evt.stopPropagation();
39822               scope.$apply(function() {
39823                 scope.isOpen = true;
39824               });
39825             }
39826           }
39827         }])
39828 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
39829
39830         .directive('uibDatepickerPopup', function() {
39831           return {
39832             require: ['ngModel', 'uibDatepickerPopup'],
39833             controller: 'UibDatepickerPopupController',
39834             scope: {
39835 <<<<<<< HEAD
39836               datepickerOptions: '=?',
39837               isOpen: '=?',
39838               currentText: '@',
39839               clearText: '@',
39840               closeText: '@'
39841 =======
39842               isOpen: '=?',
39843               currentText: '@',
39844               clearText: '@',
39845               closeText: '@',
39846               dateDisabled: '&',
39847               customClass: '&'
39848 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
39849             },
39850             link: function(scope, element, attrs, ctrls) {
39851               var ngModel = ctrls[0],
39852                 ctrl = ctrls[1];
39853
39854               ctrl.init(ngModel);
39855             }
39856           };
39857         })
39858
39859         .directive('uibDatepickerPopupWrap', function() {
39860           return {
39861             replace: true,
39862             transclude: true,
39863             templateUrl: function(element, attrs) {
39864 <<<<<<< HEAD
39865               return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';
39866 =======
39867               return attrs.templateUrl || 'uib/template/datepicker/popup.html';
39868 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
39869             }
39870           };
39871         });
39872
39873         angular.module('ui.bootstrap.debounce', [])
39874         /**
39875          * A helper, internal service that debounces a function
39876          */
39877           .factory('$$debounce', ['$timeout', function($timeout) {
39878             return function(callback, debounceTime) {
39879               var timeoutPromise;
39880
39881               return function() {
39882                 var self = this;
39883                 var args = Array.prototype.slice.call(arguments);
39884                 if (timeoutPromise) {
39885                   $timeout.cancel(timeoutPromise);
39886                 }
39887
39888                 timeoutPromise = $timeout(function() {
39889                   callback.apply(self, args);
39890                 }, debounceTime);
39891               };
39892             };
39893           }]);
39894
39895         angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
39896
39897         .constant('uibDropdownConfig', {
39898           appendToOpenClass: 'uib-dropdown-open',
39899           openClass: 'open'
39900         })
39901
39902         .service('uibDropdownService', ['$document', '$rootScope', function($document, $rootScope) {
39903           var openScope = null;
39904
39905 <<<<<<< HEAD
39906           this.open = function(dropdownScope, element) {
39907             if (!openScope) {
39908               $document.on('click', closeDropdown);
39909               element.on('keydown', keybindFilter);
39910 =======
39911           this.open = function(dropdownScope) {
39912             if (!openScope) {
39913               $document.on('click', closeDropdown);
39914               $document.on('keydown', keybindFilter);
39915 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
39916             }
39917
39918             if (openScope && openScope !== dropdownScope) {
39919               openScope.isOpen = false;
39920             }
39921
39922             openScope = dropdownScope;
39923           };
39924
39925 <<<<<<< HEAD
39926           this.close = function(dropdownScope, element) {
39927             if (openScope === dropdownScope) {
39928               openScope = null;
39929               $document.off('click', closeDropdown);
39930               element.off('keydown', keybindFilter);
39931 =======
39932           this.close = function(dropdownScope) {
39933             if (openScope === dropdownScope) {
39934               openScope = null;
39935               $document.off('click', closeDropdown);
39936               $document.off('keydown', keybindFilter);
39937 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
39938             }
39939           };
39940
39941           var closeDropdown = function(evt) {
39942             // This method may still be called during the same mouse event that
39943             // unbound this event handler. So check openScope before proceeding.
39944             if (!openScope) { return; }
39945
39946             if (evt && openScope.getAutoClose() === 'disabled') { return; }
39947
39948             if (evt && evt.which === 3) { return; }
39949
39950             var toggleElement = openScope.getToggleElement();
39951             if (evt && toggleElement && toggleElement[0].contains(evt.target)) {
39952               return;
39953             }
39954
39955             var dropdownElement = openScope.getDropdownElement();
39956             if (evt && openScope.getAutoClose() === 'outsideClick' &&
39957               dropdownElement && dropdownElement[0].contains(evt.target)) {
39958               return;
39959             }
39960
39961             openScope.isOpen = false;
39962
39963             if (!$rootScope.$$phase) {
39964               openScope.$apply();
39965             }
39966           };
39967
39968           var keybindFilter = function(evt) {
39969             if (evt.which === 27) {
39970 <<<<<<< HEAD
39971               evt.stopPropagation();
39972 =======
39973 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
39974               openScope.focusToggleElement();
39975               closeDropdown();
39976             } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen) {
39977               evt.preventDefault();
39978               evt.stopPropagation();
39979               openScope.focusDropdownEntry(evt.which);
39980             }
39981           };
39982         }])
39983
39984         .controller('UibDropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', function($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest) {
39985           var self = this,
39986             scope = $scope.$new(), // create a child scope so we are not polluting original one
39987             templateScope,
39988             appendToOpenClass = dropdownConfig.appendToOpenClass,
39989             openClass = dropdownConfig.openClass,
39990             getIsOpen,
39991             setIsOpen = angular.noop,
39992             toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
39993             appendToBody = false,
39994             appendTo = null,
39995             keynavEnabled = false,
39996             selectedOption = null,
39997             body = $document.find('body');
39998
39999           $element.addClass('dropdown');
40000
40001           this.init = function() {
40002             if ($attrs.isOpen) {
40003               getIsOpen = $parse($attrs.isOpen);
40004               setIsOpen = getIsOpen.assign;
40005
40006               $scope.$watch(getIsOpen, function(value) {
40007                 scope.isOpen = !!value;
40008               });
40009             }
40010
40011             if (angular.isDefined($attrs.dropdownAppendTo)) {
40012               var appendToEl = $parse($attrs.dropdownAppendTo)(scope);
40013               if (appendToEl) {
40014                 appendTo = angular.element(appendToEl);
40015               }
40016             }
40017
40018             appendToBody = angular.isDefined($attrs.dropdownAppendToBody);
40019             keynavEnabled = angular.isDefined($attrs.keyboardNav);
40020
40021             if (appendToBody && !appendTo) {
40022               appendTo = body;
40023             }
40024
40025             if (appendTo && self.dropdownMenu) {
40026               appendTo.append(self.dropdownMenu);
40027               $element.on('$destroy', function handleDestroyEvent() {
40028                 self.dropdownMenu.remove();
40029               });
40030             }
40031           };
40032
40033           this.toggle = function(open) {
40034 <<<<<<< HEAD
40035             scope.isOpen = arguments.length ? !!open : !scope.isOpen;
40036             if (angular.isFunction(setIsOpen)) {
40037               setIsOpen(scope, scope.isOpen);
40038             }
40039
40040             return scope.isOpen;
40041 =======
40042             return scope.isOpen = arguments.length ? !!open : !scope.isOpen;
40043 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40044           };
40045
40046           // Allow other directives to watch status
40047           this.isOpen = function() {
40048             return scope.isOpen;
40049           };
40050
40051           scope.getToggleElement = function() {
40052             return self.toggleElement;
40053           };
40054
40055           scope.getAutoClose = function() {
40056             return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'
40057           };
40058
40059           scope.getElement = function() {
40060             return $element;
40061           };
40062
40063           scope.isKeynavEnabled = function() {
40064             return keynavEnabled;
40065           };
40066
40067           scope.focusDropdownEntry = function(keyCode) {
40068             var elems = self.dropdownMenu ? //If append to body is used.
40069               angular.element(self.dropdownMenu).find('a') :
40070               $element.find('ul').eq(0).find('a');
40071
40072             switch (keyCode) {
40073               case 40: {
40074                 if (!angular.isNumber(self.selectedOption)) {
40075                   self.selectedOption = 0;
40076                 } else {
40077                   self.selectedOption = self.selectedOption === elems.length - 1 ?
40078                     self.selectedOption :
40079                     self.selectedOption + 1;
40080                 }
40081                 break;
40082               }
40083               case 38: {
40084                 if (!angular.isNumber(self.selectedOption)) {
40085                   self.selectedOption = elems.length - 1;
40086                 } else {
40087                   self.selectedOption = self.selectedOption === 0 ?
40088                     0 : self.selectedOption - 1;
40089                 }
40090                 break;
40091               }
40092             }
40093             elems[self.selectedOption].focus();
40094           };
40095
40096           scope.getDropdownElement = function() {
40097             return self.dropdownMenu;
40098           };
40099
40100           scope.focusToggleElement = function() {
40101             if (self.toggleElement) {
40102               self.toggleElement[0].focus();
40103             }
40104           };
40105
40106           scope.$watch('isOpen', function(isOpen, wasOpen) {
40107             if (appendTo && self.dropdownMenu) {
40108               var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true),
40109                 css,
40110 <<<<<<< HEAD
40111                 rightalign,
40112                 scrollbarWidth;
40113 =======
40114                 rightalign;
40115 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40116
40117               css = {
40118                 top: pos.top + 'px',
40119                 display: isOpen ? 'block' : 'none'
40120               };
40121
40122               rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');
40123               if (!rightalign) {
40124                 css.left = pos.left + 'px';
40125                 css.right = 'auto';
40126               } else {
40127                 css.left = 'auto';
40128 <<<<<<< HEAD
40129                 scrollbarWidth = $position.scrollbarWidth(true);
40130                 css.right = window.innerWidth - scrollbarWidth -
40131 =======
40132                 css.right = window.innerWidth -
40133 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40134                   (pos.left + $element.prop('offsetWidth')) + 'px';
40135               }
40136
40137               // Need to adjust our positioning to be relative to the appendTo container
40138               // if it's not the body element
40139               if (!appendToBody) {
40140                 var appendOffset = $position.offset(appendTo);
40141
40142                 css.top = pos.top - appendOffset.top + 'px';
40143
40144                 if (!rightalign) {
40145                   css.left = pos.left - appendOffset.left + 'px';
40146                 } else {
40147                   css.right = window.innerWidth -
40148                     (pos.left - appendOffset.left + $element.prop('offsetWidth')) + 'px';
40149                 }
40150               }
40151
40152               self.dropdownMenu.css(css);
40153             }
40154
40155             var openContainer = appendTo ? appendTo : $element;
40156 <<<<<<< HEAD
40157             var hasOpenClass = openContainer.hasClass(appendTo ? appendToOpenClass : openClass);
40158
40159             if (hasOpenClass === !isOpen) {
40160               $animate[isOpen ? 'addClass' : 'removeClass'](openContainer, appendTo ? appendToOpenClass : openClass).then(function() {
40161                 if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
40162                   toggleInvoker($scope, { open: !!isOpen });
40163                 }
40164               });
40165             }
40166 =======
40167
40168             $animate[isOpen ? 'addClass' : 'removeClass'](openContainer, appendTo ? appendToOpenClass : openClass).then(function() {
40169               if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
40170                 toggleInvoker($scope, { open: !!isOpen });
40171               }
40172             });
40173 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40174
40175             if (isOpen) {
40176               if (self.dropdownMenuTemplateUrl) {
40177                 $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {
40178                   templateScope = scope.$new();
40179                   $compile(tplContent.trim())(templateScope, function(dropdownElement) {
40180                     var newEl = dropdownElement;
40181                     self.dropdownMenu.replaceWith(newEl);
40182                     self.dropdownMenu = newEl;
40183                   });
40184                 });
40185               }
40186
40187               scope.focusToggleElement();
40188 <<<<<<< HEAD
40189               uibDropdownService.open(scope, $element);
40190 =======
40191               uibDropdownService.open(scope);
40192 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40193             } else {
40194               if (self.dropdownMenuTemplateUrl) {
40195                 if (templateScope) {
40196                   templateScope.$destroy();
40197                 }
40198                 var newEl = angular.element('<ul class="dropdown-menu"></ul>');
40199                 self.dropdownMenu.replaceWith(newEl);
40200                 self.dropdownMenu = newEl;
40201               }
40202
40203 <<<<<<< HEAD
40204               uibDropdownService.close(scope, $element);
40205 =======
40206               uibDropdownService.close(scope);
40207 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40208               self.selectedOption = null;
40209             }
40210
40211             if (angular.isFunction(setIsOpen)) {
40212               setIsOpen($scope, isOpen);
40213             }
40214           });
40215 <<<<<<< HEAD
40216 =======
40217
40218           $scope.$on('$locationChangeSuccess', function() {
40219             if (scope.getAutoClose() !== 'disabled') {
40220               scope.isOpen = false;
40221             }
40222           });
40223 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40224         }])
40225
40226         .directive('uibDropdown', function() {
40227           return {
40228             controller: 'UibDropdownController',
40229             link: function(scope, element, attrs, dropdownCtrl) {
40230               dropdownCtrl.init();
40231             }
40232           };
40233         })
40234
40235         .directive('uibDropdownMenu', function() {
40236           return {
40237             restrict: 'A',
40238             require: '?^uibDropdown',
40239             link: function(scope, element, attrs, dropdownCtrl) {
40240               if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {
40241                 return;
40242               }
40243
40244               element.addClass('dropdown-menu');
40245
40246               var tplUrl = attrs.templateUrl;
40247               if (tplUrl) {
40248                 dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;
40249               }
40250
40251               if (!dropdownCtrl.dropdownMenu) {
40252                 dropdownCtrl.dropdownMenu = element;
40253               }
40254             }
40255           };
40256         })
40257
40258         .directive('uibDropdownToggle', function() {
40259           return {
40260             require: '?^uibDropdown',
40261             link: function(scope, element, attrs, dropdownCtrl) {
40262               if (!dropdownCtrl) {
40263                 return;
40264               }
40265
40266               element.addClass('dropdown-toggle');
40267
40268               dropdownCtrl.toggleElement = element;
40269
40270               var toggleDropdown = function(event) {
40271                 event.preventDefault();
40272
40273                 if (!element.hasClass('disabled') && !attrs.disabled) {
40274                   scope.$apply(function() {
40275                     dropdownCtrl.toggle();
40276                   });
40277                 }
40278               };
40279
40280               element.bind('click', toggleDropdown);
40281
40282               // WAI-ARIA
40283               element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
40284               scope.$watch(dropdownCtrl.isOpen, function(isOpen) {
40285                 element.attr('aria-expanded', !!isOpen);
40286               });
40287
40288               scope.$on('$destroy', function() {
40289                 element.unbind('click', toggleDropdown);
40290               });
40291             }
40292           };
40293         });
40294
40295         angular.module('ui.bootstrap.stackedMap', [])
40296         /**
40297          * A helper, internal data structure that acts as a map but also allows getting / removing
40298          * elements in the LIFO order
40299          */
40300           .factory('$$stackedMap', function() {
40301             return {
40302               createNew: function() {
40303                 var stack = [];
40304
40305                 return {
40306                   add: function(key, value) {
40307                     stack.push({
40308                       key: key,
40309                       value: value
40310                     });
40311                   },
40312                   get: function(key) {
40313                     for (var i = 0; i < stack.length; i++) {
40314                       if (key === stack[i].key) {
40315                         return stack[i];
40316                       }
40317                     }
40318                   },
40319                   keys: function() {
40320                     var keys = [];
40321                     for (var i = 0; i < stack.length; i++) {
40322                       keys.push(stack[i].key);
40323                     }
40324                     return keys;
40325                   },
40326                   top: function() {
40327                     return stack[stack.length - 1];
40328                   },
40329                   remove: function(key) {
40330                     var idx = -1;
40331                     for (var i = 0; i < stack.length; i++) {
40332                       if (key === stack[i].key) {
40333                         idx = i;
40334                         break;
40335                       }
40336                     }
40337                     return stack.splice(idx, 1)[0];
40338                   },
40339                   removeTop: function() {
40340                     return stack.splice(stack.length - 1, 1)[0];
40341                   },
40342                   length: function() {
40343                     return stack.length;
40344                   }
40345                 };
40346               }
40347             };
40348           });
40349 <<<<<<< HEAD
40350         angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.position'])
40351 =======
40352         angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
40353 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40354         /**
40355          * A helper, internal data structure that stores all references attached to key
40356          */
40357           .factory('$$multiMap', function() {
40358             return {
40359               createNew: function() {
40360                 var map = {};
40361
40362                 return {
40363                   entries: function() {
40364                     return Object.keys(map).map(function(key) {
40365                       return {
40366                         key: key,
40367                         value: map[key]
40368                       };
40369                     });
40370                   },
40371                   get: function(key) {
40372                     return map[key];
40373                   },
40374                   hasKey: function(key) {
40375                     return !!map[key];
40376                   },
40377                   keys: function() {
40378                     return Object.keys(map);
40379                   },
40380                   put: function(key, value) {
40381                     if (!map[key]) {
40382                       map[key] = [];
40383                     }
40384
40385                     map[key].push(value);
40386                   },
40387                   remove: function(key, value) {
40388                     var values = map[key];
40389
40390                     if (!values) {
40391                       return;
40392                     }
40393
40394                     var idx = values.indexOf(value);
40395
40396                     if (idx !== -1) {
40397                       values.splice(idx, 1);
40398                     }
40399
40400                     if (!values.length) {
40401                       delete map[key];
40402                     }
40403                   }
40404                 };
40405               }
40406             };
40407           })
40408
40409         /**
40410          * Pluggable resolve mechanism for the modal resolve resolution
40411          * Supports UI Router's $resolve service
40412          */
40413           .provider('$uibResolve', function() {
40414             var resolve = this;
40415             this.resolver = null;
40416
40417             this.setResolver = function(resolver) {
40418               this.resolver = resolver;
40419             };
40420
40421             this.$get = ['$injector', '$q', function($injector, $q) {
40422               var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
40423               return {
40424                 resolve: function(invocables, locals, parent, self) {
40425                   if (resolver) {
40426                     return resolver.resolve(invocables, locals, parent, self);
40427                   }
40428
40429                   var promises = [];
40430
40431                   angular.forEach(invocables, function(value) {
40432                     if (angular.isFunction(value) || angular.isArray(value)) {
40433                       promises.push($q.resolve($injector.invoke(value)));
40434                     } else if (angular.isString(value)) {
40435                       promises.push($q.resolve($injector.get(value)));
40436                     } else {
40437                       promises.push($q.resolve(value));
40438                     }
40439                   });
40440
40441                   return $q.all(promises).then(function(resolves) {
40442                     var resolveObj = {};
40443                     var resolveIter = 0;
40444                     angular.forEach(invocables, function(value, key) {
40445                       resolveObj[key] = resolves[resolveIter++];
40446                     });
40447
40448                     return resolveObj;
40449                   });
40450                 }
40451               };
40452             }];
40453           })
40454
40455         /**
40456          * A helper directive for the $modal service. It creates a backdrop element.
40457          */
40458 <<<<<<< HEAD
40459           .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
40460           function($animate, $injector, $modalStack) {
40461 =======
40462           .directive('uibModalBackdrop', ['$animateCss', '$injector', '$uibModalStack',
40463           function($animateCss, $injector, $modalStack) {
40464 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40465             return {
40466               replace: true,
40467               templateUrl: 'uib/template/modal/backdrop.html',
40468               compile: function(tElement, tAttrs) {
40469                 tElement.addClass(tAttrs.backdropClass);
40470                 return linkFn;
40471               }
40472             };
40473
40474             function linkFn(scope, element, attrs) {
40475               if (attrs.modalInClass) {
40476 <<<<<<< HEAD
40477                 $animate.addClass(element, attrs.modalInClass);
40478 =======
40479                 $animateCss(element, {
40480                   addClass: attrs.modalInClass
40481                 }).start();
40482 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40483
40484                 scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
40485                   var done = setIsAsync();
40486                   if (scope.modalOptions.animation) {
40487 <<<<<<< HEAD
40488                     $animate.removeClass(element, attrs.modalInClass).then(done);
40489 =======
40490                     $animateCss(element, {
40491                       removeClass: attrs.modalInClass
40492                     }).start().then(done);
40493 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40494                   } else {
40495                     done();
40496                   }
40497                 });
40498               }
40499             }
40500           }])
40501
40502 <<<<<<< HEAD
40503           .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',
40504           function($modalStack, $q, $animateCss, $document) {
40505 =======
40506           .directive('uibModalWindow', ['$uibModalStack', '$q', '$animate', '$animateCss', '$document',
40507           function($modalStack, $q, $animate, $animateCss, $document) {
40508 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40509             return {
40510               scope: {
40511                 index: '@'
40512               },
40513               replace: true,
40514               transclude: true,
40515               templateUrl: function(tElement, tAttrs) {
40516                 return tAttrs.templateUrl || 'uib/template/modal/window.html';
40517               },
40518               link: function(scope, element, attrs) {
40519                 element.addClass(attrs.windowClass || '');
40520                 element.addClass(attrs.windowTopClass || '');
40521                 scope.size = attrs.size;
40522
40523                 scope.close = function(evt) {
40524                   var modal = $modalStack.getTop();
40525                   if (modal && modal.value.backdrop &&
40526                     modal.value.backdrop !== 'static' &&
40527                     evt.target === evt.currentTarget) {
40528                     evt.preventDefault();
40529                     evt.stopPropagation();
40530                     $modalStack.dismiss(modal.key, 'backdrop click');
40531                   }
40532                 };
40533
40534                 // moved from template to fix issue #2280
40535                 element.on('click', scope.close);
40536
40537                 // This property is only added to the scope for the purpose of detecting when this directive is rendered.
40538                 // We can detect that by using this property in the template associated with this directive and then use
40539                 // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
40540                 scope.$isRendered = true;
40541
40542                 // Deferred object that will be resolved when this modal is render.
40543                 var modalRenderDeferObj = $q.defer();
40544                 // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.
40545                 // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.
40546                 attrs.$observe('modalRender', function(value) {
40547                   if (value === 'true') {
40548                     modalRenderDeferObj.resolve();
40549                   }
40550                 });
40551
40552                 modalRenderDeferObj.promise.then(function() {
40553                   var animationPromise = null;
40554
40555                   if (attrs.modalInClass) {
40556                     animationPromise = $animateCss(element, {
40557                       addClass: attrs.modalInClass
40558                     }).start();
40559
40560                     scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
40561                       var done = setIsAsync();
40562 <<<<<<< HEAD
40563                       $animateCss(element, {
40564                         removeClass: attrs.modalInClass
40565                       }).start().then(done);
40566 =======
40567                       if ($animateCss) {
40568                         $animateCss(element, {
40569                           removeClass: attrs.modalInClass
40570                         }).start().then(done);
40571                       } else {
40572                         $animate.removeClass(element, attrs.modalInClass).then(done);
40573                       }
40574 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40575                     });
40576                   }
40577
40578
40579                   $q.when(animationPromise).then(function() {
40580 <<<<<<< HEAD
40581                     // Notify {@link $modalStack} that modal is rendered.
40582                     var modal = $modalStack.getTop();
40583                     if (modal) {
40584                       $modalStack.modalRendered(modal.key);
40585                     }
40586
40587 =======
40588 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40589                     /**
40590                      * If something within the freshly-opened modal already has focus (perhaps via a
40591                      * directive that causes focus). then no need to try and focus anything.
40592                      */
40593                     if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
40594                       var inputWithAutofocus = element[0].querySelector('[autofocus]');
40595                       /**
40596                        * Auto-focusing of a freshly-opened modal element causes any child elements
40597                        * with the autofocus attribute to lose focus. This is an issue on touch
40598                        * based devices which will show and then hide the onscreen keyboard.
40599                        * Attempts to refocus the autofocus element via JavaScript will not reopen
40600                        * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
40601                        * the modal element if the modal does not contain an autofocus element.
40602                        */
40603                       if (inputWithAutofocus) {
40604                         inputWithAutofocus.focus();
40605                       } else {
40606                         element[0].focus();
40607                       }
40608                     }
40609                   });
40610 <<<<<<< HEAD
40611 =======
40612
40613                   // Notify {@link $modalStack} that modal is rendered.
40614                   var modal = $modalStack.getTop();
40615                   if (modal) {
40616                     $modalStack.modalRendered(modal.key);
40617                   }
40618 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40619                 });
40620               }
40621             };
40622           }])
40623
40624           .directive('uibModalAnimationClass', function() {
40625             return {
40626               compile: function(tElement, tAttrs) {
40627                 if (tAttrs.modalAnimation) {
40628                   tElement.addClass(tAttrs.uibModalAnimationClass);
40629                 }
40630               }
40631             };
40632           })
40633
40634           .directive('uibModalTransclude', function() {
40635             return {
40636               link: function(scope, element, attrs, controller, transclude) {
40637                 transclude(scope.$parent, function(clone) {
40638                   element.empty();
40639                   element.append(clone);
40640                 });
40641               }
40642             };
40643           })
40644
40645           .factory('$uibModalStack', ['$animate', '$animateCss', '$document',
40646 <<<<<<< HEAD
40647             '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
40648             function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {
40649 =======
40650             '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap',
40651             function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap) {
40652 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40653               var OPENED_MODAL_CLASS = 'modal-open';
40654
40655               var backdropDomEl, backdropScope;
40656               var openedWindows = $$stackedMap.createNew();
40657               var openedClasses = $$multiMap.createNew();
40658               var $modalStack = {
40659                 NOW_CLOSING_EVENT: 'modal.stack.now-closing'
40660               };
40661 <<<<<<< HEAD
40662               var topModalIndex = 0;
40663               var previousTopOpenedModal = null;
40664
40665               //Modal focus behavior
40666               var tabableSelector = 'a[href], area[href], input:not([disabled]), ' +
40667                 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' +
40668                 'iframe, object, embed, *[tabindex], *[contenteditable=true]';
40669               var scrollbarPadding;
40670
40671               function isVisible(element) {
40672                 return !!(element.offsetWidth ||
40673                   element.offsetHeight ||
40674                   element.getClientRects().length);
40675               }
40676 =======
40677
40678               //Modal focus behavior
40679               var focusableElementList;
40680               var focusIndex = 0;
40681               var tababbleSelector = 'a[href], area[href], input:not([disabled]), ' +
40682                 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' +
40683                 'iframe, object, embed, *[tabindex], *[contenteditable=true]';
40684 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40685
40686               function backdropIndex() {
40687                 var topBackdropIndex = -1;
40688                 var opened = openedWindows.keys();
40689                 for (var i = 0; i < opened.length; i++) {
40690                   if (openedWindows.get(opened[i]).value.backdrop) {
40691                     topBackdropIndex = i;
40692                   }
40693                 }
40694 <<<<<<< HEAD
40695
40696                 // If any backdrop exist, ensure that it's index is always
40697                 // right below the top modal
40698                 if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
40699                   topBackdropIndex = topModalIndex;
40700                 }
40701 =======
40702 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40703                 return topBackdropIndex;
40704               }
40705
40706               $rootScope.$watch(backdropIndex, function(newBackdropIndex) {
40707                 if (backdropScope) {
40708                   backdropScope.index = newBackdropIndex;
40709                 }
40710               });
40711
40712               function removeModalWindow(modalInstance, elementToReceiveFocus) {
40713                 var modalWindow = openedWindows.get(modalInstance).value;
40714                 var appendToElement = modalWindow.appendTo;
40715
40716                 //clean up the stack
40717                 openedWindows.remove(modalInstance);
40718 <<<<<<< HEAD
40719                 previousTopOpenedModal = openedWindows.top();
40720                 if (previousTopOpenedModal) {
40721                   topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
40722                 }
40723 =======
40724 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40725
40726                 removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
40727                   var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
40728                   openedClasses.remove(modalBodyClass, modalInstance);
40729 <<<<<<< HEAD
40730                   var areAnyOpen = openedClasses.hasKey(modalBodyClass);
40731                   appendToElement.toggleClass(modalBodyClass, areAnyOpen);
40732                   if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
40733                     if (scrollbarPadding.originalRight) {
40734                       appendToElement.css({paddingRight: scrollbarPadding.originalRight + 'px'});
40735                     } else {
40736                       appendToElement.css({paddingRight: ''});
40737                     }
40738                     scrollbarPadding = null;
40739                   }
40740                   toggleTopWindowClass(true);
40741                 }, modalWindow.closedDeferred);
40742 =======
40743                   appendToElement.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass));
40744                   toggleTopWindowClass(true);
40745                 });
40746 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40747                 checkRemoveBackdrop();
40748
40749                 //move focus to specified element if available, or else to body
40750                 if (elementToReceiveFocus && elementToReceiveFocus.focus) {
40751                   elementToReceiveFocus.focus();
40752                 } else if (appendToElement.focus) {
40753                   appendToElement.focus();
40754                 }
40755               }
40756
40757               // Add or remove "windowTopClass" from the top window in the stack
40758               function toggleTopWindowClass(toggleSwitch) {
40759                 var modalWindow;
40760
40761                 if (openedWindows.length() > 0) {
40762                   modalWindow = openedWindows.top().value;
40763                   modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
40764                 }
40765               }
40766
40767               function checkRemoveBackdrop() {
40768                 //remove backdrop if no longer needed
40769                 if (backdropDomEl && backdropIndex() === -1) {
40770                   var backdropScopeRef = backdropScope;
40771                   removeAfterAnimate(backdropDomEl, backdropScope, function() {
40772                     backdropScopeRef = null;
40773                   });
40774                   backdropDomEl = undefined;
40775                   backdropScope = undefined;
40776                 }
40777               }
40778
40779               function removeAfterAnimate(domEl, scope, done, closedDeferred) {
40780                 var asyncDeferred;
40781                 var asyncPromise = null;
40782                 var setIsAsync = function() {
40783                   if (!asyncDeferred) {
40784                     asyncDeferred = $q.defer();
40785                     asyncPromise = asyncDeferred.promise;
40786                   }
40787
40788                   return function asyncDone() {
40789                     asyncDeferred.resolve();
40790                   };
40791                 };
40792                 scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);
40793
40794                 // Note that it's intentional that asyncPromise might be null.
40795                 // That's when setIsAsync has not been called during the
40796                 // NOW_CLOSING_EVENT broadcast.
40797                 return $q.when(asyncPromise).then(afterAnimating);
40798
40799                 function afterAnimating() {
40800                   if (afterAnimating.done) {
40801                     return;
40802                   }
40803                   afterAnimating.done = true;
40804
40805 <<<<<<< HEAD
40806                   $animate.leave(domEl).then(function() {
40807 =======
40808                   $animateCss(domEl, {
40809                     event: 'leave'
40810                   }).start().then(function() {
40811 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40812                     domEl.remove();
40813                     if (closedDeferred) {
40814                       closedDeferred.resolve();
40815                     }
40816                   });
40817
40818                   scope.$destroy();
40819                   if (done) {
40820                     done();
40821                   }
40822                 }
40823               }
40824
40825               $document.on('keydown', keydownListener);
40826
40827               $rootScope.$on('$destroy', function() {
40828                 $document.off('keydown', keydownListener);
40829               });
40830
40831               function keydownListener(evt) {
40832                 if (evt.isDefaultPrevented()) {
40833                   return evt;
40834                 }
40835
40836                 var modal = openedWindows.top();
40837                 if (modal) {
40838                   switch (evt.which) {
40839                     case 27: {
40840                       if (modal.value.keyboard) {
40841                         evt.preventDefault();
40842                         $rootScope.$apply(function() {
40843                           $modalStack.dismiss(modal.key, 'escape key press');
40844                         });
40845                       }
40846                       break;
40847                     }
40848                     case 9: {
40849 <<<<<<< HEAD
40850                       var list = $modalStack.loadFocusElementList(modal);
40851                       var focusChanged = false;
40852                       if (evt.shiftKey) {
40853                         if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {
40854                           focusChanged = $modalStack.focusLastFocusableElement(list);
40855                         }
40856                       } else {
40857                         if ($modalStack.isFocusInLastItem(evt, list)) {
40858                           focusChanged = $modalStack.focusFirstFocusableElement(list);
40859 =======
40860                       $modalStack.loadFocusElementList(modal);
40861                       var focusChanged = false;
40862                       if (evt.shiftKey) {
40863                         if ($modalStack.isFocusInFirstItem(evt)) {
40864                           focusChanged = $modalStack.focusLastFocusableElement();
40865                         }
40866                       } else {
40867                         if ($modalStack.isFocusInLastItem(evt)) {
40868                           focusChanged = $modalStack.focusFirstFocusableElement();
40869 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40870                         }
40871                       }
40872
40873                       if (focusChanged) {
40874                         evt.preventDefault();
40875                         evt.stopPropagation();
40876                       }
40877 <<<<<<< HEAD
40878
40879 =======
40880 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40881                       break;
40882                     }
40883                   }
40884                 }
40885               }
40886
40887               $modalStack.open = function(modalInstance, modal) {
40888                 var modalOpener = $document[0].activeElement,
40889                   modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
40890
40891                 toggleTopWindowClass(false);
40892
40893 <<<<<<< HEAD
40894                 // Store the current top first, to determine what index we ought to use
40895                 // for the current top modal
40896                 previousTopOpenedModal = openedWindows.top();
40897
40898 =======
40899 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40900                 openedWindows.add(modalInstance, {
40901                   deferred: modal.deferred,
40902                   renderDeferred: modal.renderDeferred,
40903                   closedDeferred: modal.closedDeferred,
40904                   modalScope: modal.scope,
40905                   backdrop: modal.backdrop,
40906                   keyboard: modal.keyboard,
40907                   openedClass: modal.openedClass,
40908                   windowTopClass: modal.windowTopClass,
40909                   animation: modal.animation,
40910                   appendTo: modal.appendTo
40911                 });
40912
40913                 openedClasses.put(modalBodyClass, modalInstance);
40914
40915                 var appendToElement = modal.appendTo,
40916                     currBackdropIndex = backdropIndex();
40917
40918                 if (!appendToElement.length) {
40919                   throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
40920                 }
40921
40922                 if (currBackdropIndex >= 0 && !backdropDomEl) {
40923                   backdropScope = $rootScope.$new(true);
40924                   backdropScope.modalOptions = modal;
40925                   backdropScope.index = currBackdropIndex;
40926                   backdropDomEl = angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');
40927                   backdropDomEl.attr('backdrop-class', modal.backdropClass);
40928                   if (modal.animation) {
40929                     backdropDomEl.attr('modal-animation', 'true');
40930                   }
40931                   $compile(backdropDomEl)(backdropScope);
40932                   $animate.enter(backdropDomEl, appendToElement);
40933 <<<<<<< HEAD
40934                   scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
40935                   if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
40936                     appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});
40937                   }
40938                 }
40939
40940                 // Set the top modal index based on the index of the previous top modal
40941                 topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
40942 =======
40943                 }
40944
40945 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40946                 var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
40947                 angularDomEl.attr({
40948                   'template-url': modal.windowTemplateUrl,
40949                   'window-class': modal.windowClass,
40950                   'window-top-class': modal.windowTopClass,
40951                   'size': modal.size,
40952 <<<<<<< HEAD
40953                   'index': topModalIndex,
40954 =======
40955                   'index': openedWindows.length() - 1,
40956 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40957                   'animate': 'animate'
40958                 }).html(modal.content);
40959                 if (modal.animation) {
40960                   angularDomEl.attr('modal-animation', 'true');
40961                 }
40962
40963 <<<<<<< HEAD
40964                 appendToElement.addClass(modalBodyClass);
40965                 $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);
40966
40967                 openedWindows.top().value.modalDomEl = angularDomEl;
40968                 openedWindows.top().value.modalOpener = modalOpener;
40969 =======
40970                 $animate.enter(angularDomEl, appendToElement)
40971                   .then(function() {
40972                     $compile(angularDomEl)(modal.scope);
40973                     $animate.addClass(appendToElement, modalBodyClass);
40974                   });
40975
40976                 openedWindows.top().value.modalDomEl = angularDomEl;
40977                 openedWindows.top().value.modalOpener = modalOpener;
40978
40979                 $modalStack.clearFocusListCache();
40980 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
40981               };
40982
40983               function broadcastClosing(modalWindow, resultOrReason, closing) {
40984                 return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
40985               }
40986
40987               $modalStack.close = function(modalInstance, result) {
40988                 var modalWindow = openedWindows.get(modalInstance);
40989                 if (modalWindow && broadcastClosing(modalWindow, result, true)) {
40990                   modalWindow.value.modalScope.$$uibDestructionScheduled = true;
40991                   modalWindow.value.deferred.resolve(result);
40992                   removeModalWindow(modalInstance, modalWindow.value.modalOpener);
40993                   return true;
40994                 }
40995                 return !modalWindow;
40996               };
40997
40998               $modalStack.dismiss = function(modalInstance, reason) {
40999                 var modalWindow = openedWindows.get(modalInstance);
41000                 if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
41001                   modalWindow.value.modalScope.$$uibDestructionScheduled = true;
41002                   modalWindow.value.deferred.reject(reason);
41003                   removeModalWindow(modalInstance, modalWindow.value.modalOpener);
41004                   return true;
41005                 }
41006                 return !modalWindow;
41007               };
41008
41009               $modalStack.dismissAll = function(reason) {
41010                 var topModal = this.getTop();
41011                 while (topModal && this.dismiss(topModal.key, reason)) {
41012                   topModal = this.getTop();
41013                 }
41014               };
41015
41016               $modalStack.getTop = function() {
41017                 return openedWindows.top();
41018               };
41019
41020               $modalStack.modalRendered = function(modalInstance) {
41021                 var modalWindow = openedWindows.get(modalInstance);
41022                 if (modalWindow) {
41023                   modalWindow.value.renderDeferred.resolve();
41024                 }
41025               };
41026
41027 <<<<<<< HEAD
41028               $modalStack.focusFirstFocusableElement = function(list) {
41029                 if (list.length > 0) {
41030                   list[0].focus();
41031 =======
41032               $modalStack.focusFirstFocusableElement = function() {
41033                 if (focusableElementList.length > 0) {
41034                   focusableElementList[0].focus();
41035 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41036                   return true;
41037                 }
41038                 return false;
41039               };
41040 <<<<<<< HEAD
41041
41042               $modalStack.focusLastFocusableElement = function(list) {
41043                 if (list.length > 0) {
41044                   list[list.length - 1].focus();
41045 =======
41046               $modalStack.focusLastFocusableElement = function() {
41047                 if (focusableElementList.length > 0) {
41048                   focusableElementList[focusableElementList.length - 1].focus();
41049 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41050                   return true;
41051                 }
41052                 return false;
41053               };
41054
41055 <<<<<<< HEAD
41056               $modalStack.isModalFocused = function(evt, modalWindow) {
41057                 if (evt && modalWindow) {
41058                   var modalDomEl = modalWindow.value.modalDomEl;
41059                   if (modalDomEl && modalDomEl.length) {
41060                     return (evt.target || evt.srcElement) === modalDomEl[0];
41061                   }
41062 =======
41063               $modalStack.isFocusInFirstItem = function(evt) {
41064                 if (focusableElementList.length > 0) {
41065                   return (evt.target || evt.srcElement) === focusableElementList[0];
41066 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41067                 }
41068                 return false;
41069               };
41070
41071 <<<<<<< HEAD
41072               $modalStack.isFocusInFirstItem = function(evt, list) {
41073                 if (list.length > 0) {
41074                   return (evt.target || evt.srcElement) === list[0];
41075 =======
41076               $modalStack.isFocusInLastItem = function(evt) {
41077                 if (focusableElementList.length > 0) {
41078                   return (evt.target || evt.srcElement) === focusableElementList[focusableElementList.length - 1];
41079 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41080                 }
41081                 return false;
41082               };
41083
41084 <<<<<<< HEAD
41085               $modalStack.isFocusInLastItem = function(evt, list) {
41086                 if (list.length > 0) {
41087                   return (evt.target || evt.srcElement) === list[list.length - 1];
41088                 }
41089                 return false;
41090               };
41091
41092               $modalStack.loadFocusElementList = function(modalWindow) {
41093                 if (modalWindow) {
41094                   var modalDomE1 = modalWindow.value.modalDomEl;
41095                   if (modalDomE1 && modalDomE1.length) {
41096                     var elements = modalDomE1[0].querySelectorAll(tabableSelector);
41097                     return elements ?
41098                       Array.prototype.filter.call(elements, function(element) {
41099                         return isVisible(element);
41100                       }) : elements;
41101 =======
41102               $modalStack.clearFocusListCache = function() {
41103                 focusableElementList = [];
41104                 focusIndex = 0;
41105               };
41106
41107               $modalStack.loadFocusElementList = function(modalWindow) {
41108                 if (focusableElementList === undefined || !focusableElementList.length) {
41109                   if (modalWindow) {
41110                     var modalDomE1 = modalWindow.value.modalDomEl;
41111                     if (modalDomE1 && modalDomE1.length) {
41112                       focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector);
41113                     }
41114 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41115                   }
41116                 }
41117               };
41118
41119               return $modalStack;
41120             }])
41121
41122           .provider('$uibModal', function() {
41123             var $modalProvider = {
41124               options: {
41125                 animation: true,
41126                 backdrop: true, //can also be false or 'static'
41127                 keyboard: true
41128               },
41129               $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
41130                 function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
41131                   var $modal = {};
41132
41133                   function getTemplatePromise(options) {
41134                     return options.template ? $q.when(options.template) :
41135                       $templateRequest(angular.isFunction(options.templateUrl) ?
41136                         options.templateUrl() : options.templateUrl);
41137                   }
41138
41139                   var promiseChain = null;
41140                   $modal.getPromiseChain = function() {
41141                     return promiseChain;
41142                   };
41143
41144                   $modal.open = function(modalOptions) {
41145                     var modalResultDeferred = $q.defer();
41146                     var modalOpenedDeferred = $q.defer();
41147                     var modalClosedDeferred = $q.defer();
41148                     var modalRenderDeferred = $q.defer();
41149
41150                     //prepare an instance of a modal to be injected into controllers and returned to a caller
41151                     var modalInstance = {
41152                       result: modalResultDeferred.promise,
41153                       opened: modalOpenedDeferred.promise,
41154                       closed: modalClosedDeferred.promise,
41155                       rendered: modalRenderDeferred.promise,
41156                       close: function (result) {
41157                         return $modalStack.close(modalInstance, result);
41158                       },
41159                       dismiss: function (reason) {
41160                         return $modalStack.dismiss(modalInstance, reason);
41161                       }
41162                     };
41163
41164                     //merge and clean up options
41165                     modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
41166                     modalOptions.resolve = modalOptions.resolve || {};
41167                     modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);
41168
41169                     //verify options
41170                     if (!modalOptions.template && !modalOptions.templateUrl) {
41171                       throw new Error('One of template or templateUrl options is required.');
41172                     }
41173
41174                     var templateAndResolvePromise =
41175                       $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
41176
41177                     function resolveWithTemplate() {
41178                       return templateAndResolvePromise;
41179                     }
41180
41181                     // Wait for the resolution of the existing promise chain.
41182                     // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
41183                     // Then add to $modalStack and resolve opened.
41184                     // Finally clean up the chain variable if no subsequent modal has overwritten it.
41185                     var samePromise;
41186                     samePromise = promiseChain = $q.all([promiseChain])
41187                       .then(resolveWithTemplate, resolveWithTemplate)
41188                       .then(function resolveSuccess(tplAndVars) {
41189                         var providedScope = modalOptions.scope || $rootScope;
41190
41191                         var modalScope = providedScope.$new();
41192                         modalScope.$close = modalInstance.close;
41193                         modalScope.$dismiss = modalInstance.dismiss;
41194
41195                         modalScope.$on('$destroy', function() {
41196                           if (!modalScope.$$uibDestructionScheduled) {
41197                             modalScope.$dismiss('$uibUnscheduledDestruction');
41198                           }
41199                         });
41200
41201 <<<<<<< HEAD
41202                         var ctrlInstance, ctrlInstantiate, ctrlLocals = {};
41203 =======
41204                         var ctrlInstance, ctrlLocals = {};
41205 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41206
41207                         //controllers
41208                         if (modalOptions.controller) {
41209                           ctrlLocals.$scope = modalScope;
41210 <<<<<<< HEAD
41211                           ctrlLocals.$scope.$resolve = {};
41212                           ctrlLocals.$uibModalInstance = modalInstance;
41213                           angular.forEach(tplAndVars[1], function(value, key) {
41214                             ctrlLocals[key] = value;
41215                             ctrlLocals.$scope.$resolve[key] = value;
41216                           });
41217
41218                           // the third param will make the controller instantiate later,private api
41219                           // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
41220                           ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
41221                           if (modalOptions.controllerAs && modalOptions.bindToController) {
41222                             ctrlInstance = ctrlInstantiate.instance;
41223                             ctrlInstance.$close = modalScope.$close;
41224                             ctrlInstance.$dismiss = modalScope.$dismiss;
41225                             angular.extend(ctrlInstance, {
41226                               $resolve: ctrlLocals.$scope.$resolve
41227                             }, providedScope);
41228                           }
41229
41230                           ctrlInstance = ctrlInstantiate();
41231
41232                           if (angular.isFunction(ctrlInstance.$onInit)) {
41233                             ctrlInstance.$onInit();
41234 =======
41235                           ctrlLocals.$uibModalInstance = modalInstance;
41236                           angular.forEach(tplAndVars[1], function(value, key) {
41237                             ctrlLocals[key] = value;
41238                           });
41239
41240                           ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
41241                           if (modalOptions.controllerAs) {
41242                             if (modalOptions.bindToController) {
41243                               ctrlInstance.$close = modalScope.$close;
41244                               ctrlInstance.$dismiss = modalScope.$dismiss;
41245                               angular.extend(ctrlInstance, providedScope);
41246                             }
41247
41248                             modalScope[modalOptions.controllerAs] = ctrlInstance;
41249 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41250                           }
41251                         }
41252
41253                         $modalStack.open(modalInstance, {
41254                           scope: modalScope,
41255                           deferred: modalResultDeferred,
41256                           renderDeferred: modalRenderDeferred,
41257                           closedDeferred: modalClosedDeferred,
41258                           content: tplAndVars[0],
41259                           animation: modalOptions.animation,
41260                           backdrop: modalOptions.backdrop,
41261                           keyboard: modalOptions.keyboard,
41262                           backdropClass: modalOptions.backdropClass,
41263                           windowTopClass: modalOptions.windowTopClass,
41264                           windowClass: modalOptions.windowClass,
41265                           windowTemplateUrl: modalOptions.windowTemplateUrl,
41266                           size: modalOptions.size,
41267                           openedClass: modalOptions.openedClass,
41268                           appendTo: modalOptions.appendTo
41269                         });
41270                         modalOpenedDeferred.resolve(true);
41271
41272                     }, function resolveError(reason) {
41273                       modalOpenedDeferred.reject(reason);
41274                       modalResultDeferred.reject(reason);
41275                     })['finally'](function() {
41276                       if (promiseChain === samePromise) {
41277                         promiseChain = null;
41278                       }
41279                     });
41280
41281                     return modalInstance;
41282                   };
41283
41284                   return $modal;
41285                 }
41286               ]
41287             };
41288
41289             return $modalProvider;
41290           });
41291
41292         angular.module('ui.bootstrap.paging', [])
41293         /**
41294          * Helper internal service for generating common controller code between the
41295          * pager and pagination components
41296          */
41297         .factory('uibPaging', ['$parse', function($parse) {
41298           return {
41299             create: function(ctrl, $scope, $attrs) {
41300               ctrl.setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
41301               ctrl.ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl
41302 <<<<<<< HEAD
41303               ctrl._watchers = [];
41304 =======
41305 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41306
41307               ctrl.init = function(ngModelCtrl, config) {
41308                 ctrl.ngModelCtrl = ngModelCtrl;
41309                 ctrl.config = config;
41310
41311                 ngModelCtrl.$render = function() {
41312                   ctrl.render();
41313                 };
41314
41315                 if ($attrs.itemsPerPage) {
41316 <<<<<<< HEAD
41317                   ctrl._watchers.push($scope.$parent.$watch($attrs.itemsPerPage, function(value) {
41318                     ctrl.itemsPerPage = parseInt(value, 10);
41319                     $scope.totalPages = ctrl.calculateTotalPages();
41320                     ctrl.updatePage();
41321                   }));
41322 =======
41323                   $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {
41324                     ctrl.itemsPerPage = parseInt(value, 10);
41325                     $scope.totalPages = ctrl.calculateTotalPages();
41326                     ctrl.updatePage();
41327                   });
41328 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41329                 } else {
41330                   ctrl.itemsPerPage = config.itemsPerPage;
41331                 }
41332
41333                 $scope.$watch('totalItems', function(newTotal, oldTotal) {
41334                   if (angular.isDefined(newTotal) || newTotal !== oldTotal) {
41335                     $scope.totalPages = ctrl.calculateTotalPages();
41336                     ctrl.updatePage();
41337                   }
41338                 });
41339               };
41340
41341               ctrl.calculateTotalPages = function() {
41342                 var totalPages = ctrl.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / ctrl.itemsPerPage);
41343                 return Math.max(totalPages || 0, 1);
41344               };
41345
41346               ctrl.render = function() {
41347                 $scope.page = parseInt(ctrl.ngModelCtrl.$viewValue, 10) || 1;
41348               };
41349
41350               $scope.selectPage = function(page, evt) {
41351                 if (evt) {
41352                   evt.preventDefault();
41353                 }
41354
41355                 var clickAllowed = !$scope.ngDisabled || !evt;
41356                 if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {
41357                   if (evt && evt.target) {
41358                     evt.target.blur();
41359                   }
41360                   ctrl.ngModelCtrl.$setViewValue(page);
41361                   ctrl.ngModelCtrl.$render();
41362                 }
41363               };
41364
41365               $scope.getText = function(key) {
41366                 return $scope[key + 'Text'] || ctrl.config[key + 'Text'];
41367               };
41368
41369               $scope.noPrevious = function() {
41370                 return $scope.page === 1;
41371               };
41372
41373               $scope.noNext = function() {
41374                 return $scope.page === $scope.totalPages;
41375               };
41376
41377               ctrl.updatePage = function() {
41378                 ctrl.setNumPages($scope.$parent, $scope.totalPages); // Readonly variable
41379
41380                 if ($scope.page > $scope.totalPages) {
41381                   $scope.selectPage($scope.totalPages);
41382                 } else {
41383                   ctrl.ngModelCtrl.$render();
41384                 }
41385               };
41386 <<<<<<< HEAD
41387
41388               $scope.$on('$destroy', function() {
41389                 while (ctrl._watchers.length) {
41390                   ctrl._watchers.shift()();
41391                 }
41392               });
41393 =======
41394 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41395             }
41396           };
41397         }]);
41398
41399         angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging'])
41400
41401         .controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function($scope, $attrs, uibPaging, uibPagerConfig) {
41402           $scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align;
41403
41404           uibPaging.create(this, $scope, $attrs);
41405         }])
41406
41407         .constant('uibPagerConfig', {
41408           itemsPerPage: 10,
41409           previousText: '« Previous',
41410           nextText: 'Next »',
41411           align: true
41412         })
41413
41414         .directive('uibPager', ['uibPagerConfig', function(uibPagerConfig) {
41415           return {
41416             scope: {
41417               totalItems: '=',
41418               previousText: '@',
41419               nextText: '@',
41420               ngDisabled: '='
41421             },
41422             require: ['uibPager', '?ngModel'],
41423             controller: 'UibPagerController',
41424             controllerAs: 'pager',
41425             templateUrl: function(element, attrs) {
41426               return attrs.templateUrl || 'uib/template/pager/pager.html';
41427             },
41428             replace: true,
41429             link: function(scope, element, attrs, ctrls) {
41430               var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
41431
41432               if (!ngModelCtrl) {
41433                 return; // do nothing if no ng-model
41434               }
41435
41436               paginationCtrl.init(ngModelCtrl, uibPagerConfig);
41437             }
41438           };
41439         }]);
41440
41441         angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging'])
41442         .controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {
41443           var ctrl = this;
41444           // Setup configuration parameters
41445           var maxSize = angular.isDefined($attrs.maxSize) ? $scope.$parent.$eval($attrs.maxSize) : uibPaginationConfig.maxSize,
41446             rotate = angular.isDefined($attrs.rotate) ? $scope.$parent.$eval($attrs.rotate) : uibPaginationConfig.rotate,
41447             forceEllipses = angular.isDefined($attrs.forceEllipses) ? $scope.$parent.$eval($attrs.forceEllipses) : uibPaginationConfig.forceEllipses,
41448 <<<<<<< HEAD
41449             boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers,
41450             pageLabel = angular.isDefined($attrs.pageLabel) ? function(idx) { return $scope.$parent.$eval($attrs.pageLabel, {$page: idx}); } : angular.identity;
41451 =======
41452             boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers;
41453 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41454           $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks;
41455           $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks;
41456
41457           uibPaging.create(this, $scope, $attrs);
41458
41459           if ($attrs.maxSize) {
41460 <<<<<<< HEAD
41461             ctrl._watchers.push($scope.$parent.$watch($parse($attrs.maxSize), function(value) {
41462               maxSize = parseInt(value, 10);
41463               ctrl.render();
41464             }));
41465 =======
41466             $scope.$parent.$watch($parse($attrs.maxSize), function(value) {
41467               maxSize = parseInt(value, 10);
41468               ctrl.render();
41469             });
41470 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41471           }
41472
41473           // Create page object used in template
41474           function makePage(number, text, isActive) {
41475             return {
41476               number: number,
41477               text: text,
41478               active: isActive
41479             };
41480           }
41481
41482           function getPages(currentPage, totalPages) {
41483             var pages = [];
41484
41485             // Default page limits
41486             var startPage = 1, endPage = totalPages;
41487             var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;
41488
41489             // recompute if maxSize
41490             if (isMaxSized) {
41491               if (rotate) {
41492                 // Current page is displayed in the middle of the visible ones
41493                 startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
41494                 endPage = startPage + maxSize - 1;
41495
41496                 // Adjust if limit is exceeded
41497                 if (endPage > totalPages) {
41498                   endPage = totalPages;
41499                   startPage = endPage - maxSize + 1;
41500                 }
41501               } else {
41502                 // Visible pages are paginated with maxSize
41503                 startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1;
41504
41505                 // Adjust last page if limit is exceeded
41506                 endPage = Math.min(startPage + maxSize - 1, totalPages);
41507               }
41508             }
41509
41510             // Add page number links
41511             for (var number = startPage; number <= endPage; number++) {
41512 <<<<<<< HEAD
41513               var page = makePage(number, pageLabel(number), number === currentPage);
41514 =======
41515               var page = makePage(number, number, number === currentPage);
41516 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41517               pages.push(page);
41518             }
41519
41520             // Add links to move between page sets
41521             if (isMaxSized && maxSize > 0 && (!rotate || forceEllipses || boundaryLinkNumbers)) {
41522               if (startPage > 1) {
41523                 if (!boundaryLinkNumbers || startPage > 3) { //need ellipsis for all options unless range is too close to beginning
41524                 var previousPageSet = makePage(startPage - 1, '...', false);
41525                 pages.unshift(previousPageSet);
41526               }
41527                 if (boundaryLinkNumbers) {
41528                   if (startPage === 3) { //need to replace ellipsis when the buttons would be sequential
41529                     var secondPageLink = makePage(2, '2', false);
41530                     pages.unshift(secondPageLink);
41531                   }
41532                   //add the first page
41533                   var firstPageLink = makePage(1, '1', false);
41534                   pages.unshift(firstPageLink);
41535                 }
41536               }
41537
41538               if (endPage < totalPages) {
41539                 if (!boundaryLinkNumbers || endPage < totalPages - 2) { //need ellipsis for all options unless range is too close to end
41540                 var nextPageSet = makePage(endPage + 1, '...', false);
41541                 pages.push(nextPageSet);
41542               }
41543                 if (boundaryLinkNumbers) {
41544                   if (endPage === totalPages - 2) { //need to replace ellipsis when the buttons would be sequential
41545                     var secondToLastPageLink = makePage(totalPages - 1, totalPages - 1, false);
41546                     pages.push(secondToLastPageLink);
41547                   }
41548                   //add the last page
41549                   var lastPageLink = makePage(totalPages, totalPages, false);
41550                   pages.push(lastPageLink);
41551                 }
41552               }
41553             }
41554             return pages;
41555           }
41556
41557           var originalRender = this.render;
41558           this.render = function() {
41559             originalRender();
41560             if ($scope.page > 0 && $scope.page <= $scope.totalPages) {
41561               $scope.pages = getPages($scope.page, $scope.totalPages);
41562             }
41563           };
41564         }])
41565
41566         .constant('uibPaginationConfig', {
41567           itemsPerPage: 10,
41568           boundaryLinks: false,
41569           boundaryLinkNumbers: false,
41570           directionLinks: true,
41571           firstText: 'First',
41572           previousText: 'Previous',
41573           nextText: 'Next',
41574           lastText: 'Last',
41575           rotate: true,
41576           forceEllipses: false
41577         })
41578
41579         .directive('uibPagination', ['$parse', 'uibPaginationConfig', function($parse, uibPaginationConfig) {
41580           return {
41581             scope: {
41582               totalItems: '=',
41583               firstText: '@',
41584               previousText: '@',
41585               nextText: '@',
41586               lastText: '@',
41587               ngDisabled:'='
41588             },
41589             require: ['uibPagination', '?ngModel'],
41590             controller: 'UibPaginationController',
41591             controllerAs: 'pagination',
41592             templateUrl: function(element, attrs) {
41593               return attrs.templateUrl || 'uib/template/pagination/pagination.html';
41594             },
41595             replace: true,
41596             link: function(scope, element, attrs, ctrls) {
41597               var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
41598
41599               if (!ngModelCtrl) {
41600                  return; // do nothing if no ng-model
41601               }
41602
41603               paginationCtrl.init(ngModelCtrl, uibPaginationConfig);
41604             }
41605           };
41606         }]);
41607
41608         /**
41609          * The following features are still outstanding: animation as a
41610          * function, placement as a function, inside, support for more triggers than
41611          * just mouse enter/leave, html tooltips, and selector delegation.
41612          */
41613         angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])
41614
41615         /**
41616          * The $tooltip service creates tooltip- and popover-like directives as well as
41617          * houses global options for them.
41618          */
41619         .provider('$uibTooltip', function() {
41620           // The default options tooltip and popover.
41621           var defaultOptions = {
41622             placement: 'top',
41623             placementClassPrefix: '',
41624             animation: true,
41625             popupDelay: 0,
41626             popupCloseDelay: 0,
41627             useContentExp: false
41628           };
41629
41630           // Default hide triggers for each show trigger
41631           var triggerMap = {
41632             'mouseenter': 'mouseleave',
41633             'click': 'click',
41634             'outsideClick': 'outsideClick',
41635             'focus': 'blur',
41636             'none': ''
41637           };
41638
41639           // The options specified to the provider globally.
41640           var globalOptions = {};
41641
41642           /**
41643            * `options({})` allows global configuration of all tooltips in the
41644            * application.
41645            *
41646            *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
41647            *     // place tooltips left instead of top by default
41648            *     $tooltipProvider.options( { placement: 'left' } );
41649            *   });
41650            */
41651                 this.options = function(value) {
41652                         angular.extend(globalOptions, value);
41653                 };
41654
41655           /**
41656            * This allows you to extend the set of trigger mappings available. E.g.:
41657            *
41658 <<<<<<< HEAD
41659            *   $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
41660 =======
41661            *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
41662 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41663            */
41664           this.setTriggers = function setTriggers(triggers) {
41665             angular.extend(triggerMap, triggers);
41666           };
41667
41668           /**
41669            * This is a helper function for translating camel-case to snake_case.
41670            */
41671           function snake_case(name) {
41672             var regexp = /[A-Z]/g;
41673             var separator = '-';
41674             return name.replace(regexp, function(letter, pos) {
41675               return (pos ? separator : '') + letter.toLowerCase();
41676             });
41677           }
41678
41679           /**
41680            * Returns the actual instance of the $tooltip service.
41681            * TODO support multiple triggers
41682            */
41683           this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
41684             var openedTooltips = $$stackedMap.createNew();
41685             $document.on('keypress', keypressListener);
41686
41687             $rootScope.$on('$destroy', function() {
41688               $document.off('keypress', keypressListener);
41689             });
41690
41691             function keypressListener(e) {
41692               if (e.which === 27) {
41693                 var last = openedTooltips.top();
41694                 if (last) {
41695                   last.value.close();
41696                   openedTooltips.removeTop();
41697                   last = null;
41698                 }
41699               }
41700             }
41701
41702             return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
41703               options = angular.extend({}, defaultOptions, globalOptions, options);
41704
41705               /**
41706                * Returns an object of show and hide triggers.
41707                *
41708                * If a trigger is supplied,
41709                * it is used to show the tooltip; otherwise, it will use the `trigger`
41710                * option passed to the `$tooltipProvider.options` method; else it will
41711                * default to the trigger supplied to this directive factory.
41712                *
41713                * The hide trigger is based on the show trigger. If the `trigger` option
41714                * was passed to the `$tooltipProvider.options` method, it will use the
41715                * mapped trigger from `triggerMap` or the passed trigger if the map is
41716                * undefined; otherwise, it uses the `triggerMap` value of the show
41717                * trigger; else it will just use the show trigger.
41718                */
41719               function getTriggers(trigger) {
41720                 var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
41721                 var hide = show.map(function(trigger) {
41722                   return triggerMap[trigger] || trigger;
41723                 });
41724                 return {
41725                   show: show,
41726                   hide: hide
41727                 };
41728               }
41729
41730               var directiveName = snake_case(ttType);
41731
41732               var startSym = $interpolate.startSymbol();
41733               var endSym = $interpolate.endSymbol();
41734               var template =
41735 <<<<<<< HEAD
41736                 '<div '+ directiveName + '-popup ' +
41737                   'uib-title="' + startSym + 'title' + endSym + '" ' +
41738                   (options.useContentExp ?
41739                     'content-exp="contentExp()" ' :
41740                     'content="' + startSym + 'content' + endSym + '" ') +
41741                   'placement="' + startSym + 'placement' + endSym + '" ' +
41742                   'popup-class="' + startSym + 'popupClass' + endSym + '" ' +
41743                   'animation="animation" ' +
41744                   'is-open="isOpen" ' +
41745                   'origin-scope="origScope" ' +
41746                   'class="uib-position-measure"' +
41747 =======
41748                 '<div '+ directiveName + '-popup '+
41749                   'title="' + startSym + 'title' + endSym + '" '+
41750                   (options.useContentExp ?
41751                     'content-exp="contentExp()" ' :
41752                     'content="' + startSym + 'content' + endSym + '" ') +
41753                   'placement="' + startSym + 'placement' + endSym + '" '+
41754                   'popup-class="' + startSym + 'popupClass' + endSym + '" '+
41755                   'animation="animation" ' +
41756                   'is-open="isOpen"' +
41757                   'origin-scope="origScope" ' +
41758                   'style="visibility: hidden; display: block; top: -9999px; left: -9999px;"' +
41759 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41760                   '>' +
41761                 '</div>';
41762
41763               return {
41764                 compile: function(tElem, tAttrs) {
41765                   var tooltipLinker = $compile(template);
41766
41767                   return function link(scope, element, attrs, tooltipCtrl) {
41768                     var tooltip;
41769                     var tooltipLinkedScope;
41770                     var transitionTimeout;
41771                     var showTimeout;
41772                     var hideTimeout;
41773                     var positionTimeout;
41774                     var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
41775                     var triggers = getTriggers(undefined);
41776                     var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
41777                     var ttScope = scope.$new(true);
41778                     var repositionScheduled = false;
41779                     var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;
41780                     var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;
41781                     var observers = [];
41782 <<<<<<< HEAD
41783                     var lastPlacement;
41784 =======
41785 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41786
41787                     var positionTooltip = function() {
41788                       // check if tooltip exists and is not empty
41789                       if (!tooltip || !tooltip.html()) { return; }
41790
41791                       if (!positionTimeout) {
41792                         positionTimeout = $timeout(function() {
41793 <<<<<<< HEAD
41794                           var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
41795                           tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });
41796
41797                           if (!tooltip.hasClass(ttPosition.placement.split('-')[0])) {
41798                             tooltip.removeClass(lastPlacement.split('-')[0]);
41799                             tooltip.addClass(ttPosition.placement.split('-')[0]);
41800                           }
41801
41802                           if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {
41803                             tooltip.removeClass(options.placementClassPrefix + lastPlacement);
41804                             tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
41805                           }
41806
41807                           // first time through tt element will have the
41808                           // uib-position-measure class or if the placement
41809                           // has changed we need to position the arrow.
41810                           if (tooltip.hasClass('uib-position-measure')) {
41811                             $position.positionArrow(tooltip, ttPosition.placement);
41812                             tooltip.removeClass('uib-position-measure');
41813                           } else if (lastPlacement !== ttPosition.placement) {
41814                             $position.positionArrow(tooltip, ttPosition.placement);
41815                           }
41816                           lastPlacement = ttPosition.placement;
41817 =======
41818                           // Reset the positioning.
41819                           tooltip.css({ top: 0, left: 0 });
41820
41821                           // Now set the calculated positioning.
41822                           var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
41823                           tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px', visibility: 'visible' });
41824
41825                           // If the placement class is prefixed, still need
41826                           // to remove the TWBS standard class.
41827                           if (options.placementClassPrefix) {
41828                             tooltip.removeClass('top bottom left right');
41829                           }
41830
41831                           tooltip.removeClass(
41832                             options.placementClassPrefix + 'top ' +
41833                             options.placementClassPrefix + 'top-left ' +
41834                             options.placementClassPrefix + 'top-right ' +
41835                             options.placementClassPrefix + 'bottom ' +
41836                             options.placementClassPrefix + 'bottom-left ' +
41837                             options.placementClassPrefix + 'bottom-right ' +
41838                             options.placementClassPrefix + 'left ' +
41839                             options.placementClassPrefix + 'left-top ' +
41840                             options.placementClassPrefix + 'left-bottom ' +
41841                             options.placementClassPrefix + 'right ' +
41842                             options.placementClassPrefix + 'right-top ' +
41843                             options.placementClassPrefix + 'right-bottom');
41844
41845                           var placement = ttPosition.placement.split('-');
41846                           tooltip.addClass(placement[0], options.placementClassPrefix + ttPosition.placement);
41847                           $position.positionArrow(tooltip, ttPosition.placement);
41848 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41849
41850                           positionTimeout = null;
41851                         }, 0, false);
41852                       }
41853                     };
41854
41855                     // Set up the correct scope to allow transclusion later
41856                     ttScope.origScope = scope;
41857
41858                     // By default, the tooltip is not open.
41859                     // TODO add ability to start tooltip opened
41860                     ttScope.isOpen = false;
41861                     openedTooltips.add(ttScope, {
41862                       close: hide
41863                     });
41864
41865                     function toggleTooltipBind() {
41866                       if (!ttScope.isOpen) {
41867                         showTooltipBind();
41868                       } else {
41869                         hideTooltipBind();
41870                       }
41871                     }
41872
41873                     // Show the tooltip with delay if specified, otherwise show it immediately
41874                     function showTooltipBind() {
41875                       if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
41876                         return;
41877                       }
41878
41879                       cancelHide();
41880                       prepareTooltip();
41881
41882                       if (ttScope.popupDelay) {
41883                         // Do nothing if the tooltip was already scheduled to pop-up.
41884                         // This happens if show is triggered multiple times before any hide is triggered.
41885                         if (!showTimeout) {
41886                           showTimeout = $timeout(show, ttScope.popupDelay, false);
41887                         }
41888                       } else {
41889                         show();
41890                       }
41891                     }
41892
41893                     function hideTooltipBind() {
41894                       cancelShow();
41895
41896                       if (ttScope.popupCloseDelay) {
41897                         if (!hideTimeout) {
41898                           hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
41899                         }
41900                       } else {
41901                         hide();
41902                       }
41903                     }
41904
41905                     // Show the tooltip popup element.
41906                     function show() {
41907                       cancelShow();
41908                       cancelHide();
41909
41910                       // Don't show empty tooltips.
41911                       if (!ttScope.content) {
41912                         return angular.noop;
41913                       }
41914
41915                       createTooltip();
41916
41917                       // And show the tooltip.
41918                       ttScope.$evalAsync(function() {
41919                         ttScope.isOpen = true;
41920                         assignIsOpen(true);
41921                         positionTooltip();
41922                       });
41923                     }
41924
41925                     function cancelShow() {
41926                       if (showTimeout) {
41927                         $timeout.cancel(showTimeout);
41928                         showTimeout = null;
41929                       }
41930
41931                       if (positionTimeout) {
41932                         $timeout.cancel(positionTimeout);
41933                         positionTimeout = null;
41934                       }
41935                     }
41936
41937                     // Hide the tooltip popup element.
41938                     function hide() {
41939                       if (!ttScope) {
41940                         return;
41941                       }
41942
41943                       // First things first: we don't show it anymore.
41944                       ttScope.$evalAsync(function() {
41945 <<<<<<< HEAD
41946                         if (ttScope) {
41947                           ttScope.isOpen = false;
41948                           assignIsOpen(false);
41949                           // And now we remove it from the DOM. However, if we have animation, we
41950                           // need to wait for it to expire beforehand.
41951                           // FIXME: this is a placeholder for a port of the transitions library.
41952                           // The fade transition in TWBS is 150ms.
41953                           if (ttScope.animation) {
41954                             if (!transitionTimeout) {
41955                               transitionTimeout = $timeout(removeTooltip, 150, false);
41956                             }
41957                           } else {
41958                             removeTooltip();
41959                           }
41960 =======
41961                         ttScope.isOpen = false;
41962                         assignIsOpen(false);
41963                         // And now we remove it from the DOM. However, if we have animation, we
41964                         // need to wait for it to expire beforehand.
41965                         // FIXME: this is a placeholder for a port of the transitions library.
41966                         // The fade transition in TWBS is 150ms.
41967                         if (ttScope.animation) {
41968                           if (!transitionTimeout) {
41969                             transitionTimeout = $timeout(removeTooltip, 150, false);
41970                           }
41971                         } else {
41972                           removeTooltip();
41973 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41974                         }
41975                       });
41976                     }
41977
41978                     function cancelHide() {
41979                       if (hideTimeout) {
41980                         $timeout.cancel(hideTimeout);
41981                         hideTimeout = null;
41982                       }
41983 <<<<<<< HEAD
41984
41985 =======
41986 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
41987                       if (transitionTimeout) {
41988                         $timeout.cancel(transitionTimeout);
41989                         transitionTimeout = null;
41990                       }
41991                     }
41992
41993                     function createTooltip() {
41994                       // There can only be one tooltip element per directive shown at once.
41995                       if (tooltip) {
41996                         return;
41997                       }
41998
41999                       tooltipLinkedScope = ttScope.$new();
42000                       tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) {
42001                         if (appendToBody) {
42002                           $document.find('body').append(tooltip);
42003                         } else {
42004                           element.after(tooltip);
42005                         }
42006                       });
42007
42008                       prepObservers();
42009                     }
42010
42011                     function removeTooltip() {
42012                       cancelShow();
42013                       cancelHide();
42014                       unregisterObservers();
42015
42016                       if (tooltip) {
42017                         tooltip.remove();
42018                         tooltip = null;
42019                       }
42020                       if (tooltipLinkedScope) {
42021                         tooltipLinkedScope.$destroy();
42022                         tooltipLinkedScope = null;
42023                       }
42024                     }
42025
42026                     /**
42027                      * Set the initial scope values. Once
42028                      * the tooltip is created, the observers
42029                      * will be added to keep things in sync.
42030                      */
42031                     function prepareTooltip() {
42032                       ttScope.title = attrs[prefix + 'Title'];
42033                       if (contentParse) {
42034                         ttScope.content = contentParse(scope);
42035                       } else {
42036                         ttScope.content = attrs[ttType];
42037                       }
42038
42039                       ttScope.popupClass = attrs[prefix + 'Class'];
42040                       ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;
42041 <<<<<<< HEAD
42042                       var placement = $position.parsePlacement(ttScope.placement);
42043                       lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];
42044 =======
42045 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42046
42047                       var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);
42048                       var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);
42049                       ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;
42050                       ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;
42051                     }
42052
42053                     function assignIsOpen(isOpen) {
42054                       if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
42055                         isOpenParse.assign(scope, isOpen);
42056                       }
42057                     }
42058
42059                     ttScope.contentExp = function() {
42060                       return ttScope.content;
42061                     };
42062
42063                     /**
42064                      * Observe the relevant attributes.
42065                      */
42066                     attrs.$observe('disabled', function(val) {
42067                       if (val) {
42068                         cancelShow();
42069                       }
42070
42071                       if (val && ttScope.isOpen) {
42072                         hide();
42073                       }
42074                     });
42075
42076                     if (isOpenParse) {
42077                       scope.$watch(isOpenParse, function(val) {
42078                         if (ttScope && !val === ttScope.isOpen) {
42079                           toggleTooltipBind();
42080                         }
42081                       });
42082                     }
42083
42084                     function prepObservers() {
42085                       observers.length = 0;
42086
42087                       if (contentParse) {
42088                         observers.push(
42089                           scope.$watch(contentParse, function(val) {
42090                             ttScope.content = val;
42091                             if (!val && ttScope.isOpen) {
42092                               hide();
42093                             }
42094                           })
42095                         );
42096
42097                         observers.push(
42098                           tooltipLinkedScope.$watch(function() {
42099                             if (!repositionScheduled) {
42100                               repositionScheduled = true;
42101                               tooltipLinkedScope.$$postDigest(function() {
42102                                 repositionScheduled = false;
42103                                 if (ttScope && ttScope.isOpen) {
42104                                   positionTooltip();
42105                                 }
42106                               });
42107                             }
42108                           })
42109                         );
42110                       } else {
42111                         observers.push(
42112                           attrs.$observe(ttType, function(val) {
42113                             ttScope.content = val;
42114                             if (!val && ttScope.isOpen) {
42115                               hide();
42116                             } else {
42117                               positionTooltip();
42118                             }
42119                           })
42120                         );
42121                       }
42122
42123                       observers.push(
42124                         attrs.$observe(prefix + 'Title', function(val) {
42125                           ttScope.title = val;
42126                           if (ttScope.isOpen) {
42127                             positionTooltip();
42128                           }
42129                         })
42130                       );
42131
42132                       observers.push(
42133                         attrs.$observe(prefix + 'Placement', function(val) {
42134                           ttScope.placement = val ? val : options.placement;
42135                           if (ttScope.isOpen) {
42136                             positionTooltip();
42137                           }
42138                         })
42139                       );
42140                     }
42141
42142                     function unregisterObservers() {
42143                       if (observers.length) {
42144                         angular.forEach(observers, function(observer) {
42145                           observer();
42146                         });
42147                         observers.length = 0;
42148                       }
42149                     }
42150
42151                     // hide tooltips/popovers for outsideClick trigger
42152                     function bodyHideTooltipBind(e) {
42153                       if (!ttScope || !ttScope.isOpen || !tooltip) {
42154                         return;
42155                       }
42156                       // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked
42157                       if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {
42158                         hideTooltipBind();
42159                       }
42160                     }
42161
42162                     var unregisterTriggers = function() {
42163                       triggers.show.forEach(function(trigger) {
42164                         if (trigger === 'outsideClick') {
42165                           element.off('click', toggleTooltipBind);
42166                         } else {
42167                           element.off(trigger, showTooltipBind);
42168                           element.off(trigger, toggleTooltipBind);
42169                         }
42170                       });
42171                       triggers.hide.forEach(function(trigger) {
42172                         if (trigger === 'outsideClick') {
42173                           $document.off('click', bodyHideTooltipBind);
42174                         } else {
42175                           element.off(trigger, hideTooltipBind);
42176                         }
42177                       });
42178                     };
42179
42180                     function prepTriggers() {
42181                       var val = attrs[prefix + 'Trigger'];
42182                       unregisterTriggers();
42183
42184                       triggers = getTriggers(val);
42185
42186                       if (triggers.show !== 'none') {
42187                         triggers.show.forEach(function(trigger, idx) {
42188                           if (trigger === 'outsideClick') {
42189                             element.on('click', toggleTooltipBind);
42190                             $document.on('click', bodyHideTooltipBind);
42191                           } else if (trigger === triggers.hide[idx]) {
42192                             element.on(trigger, toggleTooltipBind);
42193                           } else if (trigger) {
42194                             element.on(trigger, showTooltipBind);
42195                             element.on(triggers.hide[idx], hideTooltipBind);
42196                           }
42197
42198                           element.on('keypress', function(e) {
42199                             if (e.which === 27) {
42200                               hideTooltipBind();
42201                             }
42202                           });
42203                         });
42204                       }
42205                     }
42206
42207                     prepTriggers();
42208
42209                     var animation = scope.$eval(attrs[prefix + 'Animation']);
42210                     ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;
42211
42212                     var appendToBodyVal;
42213                     var appendKey = prefix + 'AppendToBody';
42214                     if (appendKey in attrs && attrs[appendKey] === undefined) {
42215                       appendToBodyVal = true;
42216                     } else {
42217                       appendToBodyVal = scope.$eval(attrs[appendKey]);
42218                     }
42219
42220                     appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;
42221
42222 <<<<<<< HEAD
42223 =======
42224                     // if a tooltip is attached to <body> we need to remove it on
42225                     // location change as its parent scope will probably not be destroyed
42226                     // by the change.
42227                     if (appendToBody) {
42228                       scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess() {
42229                         if (ttScope.isOpen) {
42230                           hide();
42231                         }
42232                       });
42233                     }
42234
42235 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42236                     // Make sure tooltip is destroyed and removed.
42237                     scope.$on('$destroy', function onDestroyTooltip() {
42238                       unregisterTriggers();
42239                       removeTooltip();
42240                       openedTooltips.remove(ttScope);
42241                       ttScope = null;
42242                     });
42243                   };
42244                 }
42245               };
42246             };
42247           }];
42248         })
42249
42250         // This is mostly ngInclude code but with a custom scope
42251         .directive('uibTooltipTemplateTransclude', [
42252                  '$animate', '$sce', '$compile', '$templateRequest',
42253         function ($animate, $sce, $compile, $templateRequest) {
42254           return {
42255             link: function(scope, elem, attrs) {
42256               var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);
42257
42258               var changeCounter = 0,
42259                 currentScope,
42260                 previousElement,
42261                 currentElement;
42262
42263               var cleanupLastIncludeContent = function() {
42264                 if (previousElement) {
42265                   previousElement.remove();
42266                   previousElement = null;
42267                 }
42268
42269                 if (currentScope) {
42270                   currentScope.$destroy();
42271                   currentScope = null;
42272                 }
42273
42274                 if (currentElement) {
42275                   $animate.leave(currentElement).then(function() {
42276                     previousElement = null;
42277                   });
42278                   previousElement = currentElement;
42279                   currentElement = null;
42280                 }
42281               };
42282
42283               scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function(src) {
42284                 var thisChangeId = ++changeCounter;
42285
42286                 if (src) {
42287                   //set the 2nd param to true to ignore the template request error so that the inner
42288                   //contents and scope can be cleaned up.
42289                   $templateRequest(src, true).then(function(response) {
42290                     if (thisChangeId !== changeCounter) { return; }
42291                     var newScope = origScope.$new();
42292                     var template = response;
42293
42294                     var clone = $compile(template)(newScope, function(clone) {
42295                       cleanupLastIncludeContent();
42296                       $animate.enter(clone, elem);
42297                     });
42298
42299                     currentScope = newScope;
42300                     currentElement = clone;
42301
42302                     currentScope.$emit('$includeContentLoaded', src);
42303                   }, function() {
42304                     if (thisChangeId === changeCounter) {
42305                       cleanupLastIncludeContent();
42306                       scope.$emit('$includeContentError', src);
42307                     }
42308                   });
42309                   scope.$emit('$includeContentRequested', src);
42310                 } else {
42311                   cleanupLastIncludeContent();
42312                 }
42313               });
42314
42315               scope.$on('$destroy', cleanupLastIncludeContent);
42316             }
42317           };
42318         }])
42319
42320         /**
42321          * Note that it's intentional that these classes are *not* applied through $animate.
42322          * They must not be animated as they're expected to be present on the tooltip on
42323          * initialization.
42324          */
42325         .directive('uibTooltipClasses', ['$uibPosition', function($uibPosition) {
42326           return {
42327             restrict: 'A',
42328             link: function(scope, element, attrs) {
42329               // need to set the primary position so the
42330               // arrow has space during position measure.
42331               // tooltip.positionTooltip()
42332               if (scope.placement) {
42333                 // // There are no top-left etc... classes
42334                 // // in TWBS, so we need the primary position.
42335                 var position = $uibPosition.parsePlacement(scope.placement);
42336                 element.addClass(position[0]);
42337 <<<<<<< HEAD
42338 =======
42339               } else {
42340                 element.addClass('top');
42341 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42342               }
42343
42344               if (scope.popupClass) {
42345                 element.addClass(scope.popupClass);
42346               }
42347
42348               if (scope.animation()) {
42349                 element.addClass(attrs.tooltipAnimationClass);
42350               }
42351             }
42352           };
42353         }])
42354
42355         .directive('uibTooltipPopup', function() {
42356           return {
42357             replace: true,
42358             scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
42359             templateUrl: 'uib/template/tooltip/tooltip-popup.html'
42360           };
42361         })
42362
42363         .directive('uibTooltip', [ '$uibTooltip', function($uibTooltip) {
42364           return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');
42365         }])
42366
42367         .directive('uibTooltipTemplatePopup', function() {
42368           return {
42369             replace: true,
42370             scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
42371               originScope: '&' },
42372             templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'
42373           };
42374         })
42375
42376         .directive('uibTooltipTemplate', ['$uibTooltip', function($uibTooltip) {
42377           return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {
42378             useContentExp: true
42379           });
42380         }])
42381
42382         .directive('uibTooltipHtmlPopup', function() {
42383           return {
42384             replace: true,
42385             scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
42386             templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'
42387           };
42388         })
42389
42390         .directive('uibTooltipHtml', ['$uibTooltip', function($uibTooltip) {
42391           return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {
42392             useContentExp: true
42393           });
42394         }]);
42395
42396         /**
42397          * The following features are still outstanding: popup delay, animation as a
42398          * function, placement as a function, inside, support for more triggers than
42399          * just mouse enter/leave, and selector delegatation.
42400          */
42401         angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])
42402
42403         .directive('uibPopoverTemplatePopup', function() {
42404           return {
42405             replace: true,
42406 <<<<<<< HEAD
42407             scope: { uibTitle: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
42408 =======
42409             scope: { title: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
42410 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42411               originScope: '&' },
42412             templateUrl: 'uib/template/popover/popover-template.html'
42413           };
42414         })
42415
42416         .directive('uibPopoverTemplate', ['$uibTooltip', function($uibTooltip) {
42417           return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {
42418             useContentExp: true
42419           });
42420         }])
42421
42422         .directive('uibPopoverHtmlPopup', function() {
42423           return {
42424             replace: true,
42425 <<<<<<< HEAD
42426             scope: { contentExp: '&', uibTitle: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
42427 =======
42428             scope: { contentExp: '&', title: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
42429 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42430             templateUrl: 'uib/template/popover/popover-html.html'
42431           };
42432         })
42433
42434         .directive('uibPopoverHtml', ['$uibTooltip', function($uibTooltip) {
42435           return $uibTooltip('uibPopoverHtml', 'popover', 'click', {
42436             useContentExp: true
42437           });
42438         }])
42439
42440         .directive('uibPopoverPopup', function() {
42441           return {
42442             replace: true,
42443 <<<<<<< HEAD
42444             scope: { uibTitle: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
42445 =======
42446             scope: { title: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
42447 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42448             templateUrl: 'uib/template/popover/popover.html'
42449           };
42450         })
42451
42452         .directive('uibPopover', ['$uibTooltip', function($uibTooltip) {
42453           return $uibTooltip('uibPopover', 'popover', 'click');
42454         }]);
42455
42456         angular.module('ui.bootstrap.progressbar', [])
42457
42458         .constant('uibProgressConfig', {
42459           animate: true,
42460           max: 100
42461         })
42462
42463         .controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function($scope, $attrs, progressConfig) {
42464           var self = this,
42465               animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;
42466
42467           this.bars = [];
42468 <<<<<<< HEAD
42469           $scope.max = getMaxOrDefault();
42470 =======
42471           $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;
42472 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42473
42474           this.addBar = function(bar, element, attrs) {
42475             if (!animate) {
42476               element.css({'transition': 'none'});
42477             }
42478
42479             this.bars.push(bar);
42480
42481 <<<<<<< HEAD
42482             bar.max = getMaxOrDefault();
42483 =======
42484             bar.max = $scope.max;
42485 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42486             bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';
42487
42488             bar.$watch('value', function(value) {
42489               bar.recalculatePercentage();
42490             });
42491
42492             bar.recalculatePercentage = function() {
42493               var totalPercentage = self.bars.reduce(function(total, bar) {
42494                 bar.percent = +(100 * bar.value / bar.max).toFixed(2);
42495                 return total + bar.percent;
42496               }, 0);
42497
42498               if (totalPercentage > 100) {
42499                 bar.percent -= totalPercentage - 100;
42500               }
42501             };
42502
42503             bar.$on('$destroy', function() {
42504               element = null;
42505               self.removeBar(bar);
42506             });
42507           };
42508
42509           this.removeBar = function(bar) {
42510             this.bars.splice(this.bars.indexOf(bar), 1);
42511             this.bars.forEach(function (bar) {
42512               bar.recalculatePercentage();
42513             });
42514           };
42515
42516 <<<<<<< HEAD
42517           //$attrs.$observe('maxParam', function(maxParam) {
42518           $scope.$watch('maxParam', function(maxParam) {
42519             self.bars.forEach(function(bar) {
42520               bar.max = getMaxOrDefault();
42521               bar.recalculatePercentage();
42522             });
42523           });
42524
42525           function getMaxOrDefault () {
42526             return angular.isDefined($scope.maxParam) ? $scope.maxParam : progressConfig.max;
42527           }
42528 =======
42529           $scope.$watch('max', function(max) {
42530             self.bars.forEach(function(bar) {
42531               bar.max = $scope.max;
42532               bar.recalculatePercentage();
42533             });
42534           });
42535 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42536         }])
42537
42538         .directive('uibProgress', function() {
42539           return {
42540             replace: true,
42541             transclude: true,
42542             controller: 'UibProgressController',
42543             require: 'uibProgress',
42544             scope: {
42545 <<<<<<< HEAD
42546               maxParam: '=?max'
42547 =======
42548               max: '=?'
42549 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42550             },
42551             templateUrl: 'uib/template/progressbar/progress.html'
42552           };
42553         })
42554
42555         .directive('uibBar', function() {
42556           return {
42557             replace: true,
42558             transclude: true,
42559             require: '^uibProgress',
42560             scope: {
42561               value: '=',
42562               type: '@'
42563             },
42564             templateUrl: 'uib/template/progressbar/bar.html',
42565             link: function(scope, element, attrs, progressCtrl) {
42566               progressCtrl.addBar(scope, element, attrs);
42567             }
42568           };
42569         })
42570
42571         .directive('uibProgressbar', function() {
42572           return {
42573             replace: true,
42574             transclude: true,
42575             controller: 'UibProgressController',
42576             scope: {
42577               value: '=',
42578 <<<<<<< HEAD
42579               maxParam: '=?max',
42580 =======
42581               max: '=?',
42582 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42583               type: '@'
42584             },
42585             templateUrl: 'uib/template/progressbar/progressbar.html',
42586             link: function(scope, element, attrs, progressCtrl) {
42587               progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
42588             }
42589           };
42590         });
42591
42592         angular.module('ui.bootstrap.rating', [])
42593
42594         .constant('uibRatingConfig', {
42595           max: 5,
42596           stateOn: null,
42597           stateOff: null,
42598 <<<<<<< HEAD
42599           enableReset: true,
42600 =======
42601 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42602           titles : ['one', 'two', 'three', 'four', 'five']
42603         })
42604
42605         .controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function($scope, $attrs, ratingConfig) {
42606 <<<<<<< HEAD
42607           var ngModelCtrl = { $setViewValue: angular.noop },
42608             self = this;
42609 =======
42610           var ngModelCtrl = { $setViewValue: angular.noop };
42611 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42612
42613           this.init = function(ngModelCtrl_) {
42614             ngModelCtrl = ngModelCtrl_;
42615             ngModelCtrl.$render = this.render;
42616
42617             ngModelCtrl.$formatters.push(function(value) {
42618               if (angular.isNumber(value) && value << 0 !== value) {
42619                 value = Math.round(value);
42620               }
42621
42622               return value;
42623             });
42624
42625             this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
42626             this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;
42627 <<<<<<< HEAD
42628             this.enableReset = angular.isDefined($attrs.enableReset) ?
42629               $scope.$parent.$eval($attrs.enableReset) : ratingConfig.enableReset;
42630             var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles;
42631 =======
42632             var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles ;
42633 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42634             this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?
42635               tmpTitles : ratingConfig.titles;
42636
42637             var ratingStates = angular.isDefined($attrs.ratingStates) ?
42638               $scope.$parent.$eval($attrs.ratingStates) :
42639               new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max);
42640             $scope.range = this.buildTemplateObjects(ratingStates);
42641           };
42642
42643           this.buildTemplateObjects = function(states) {
42644             for (var i = 0, n = states.length; i < n; i++) {
42645               states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);
42646             }
42647             return states;
42648           };
42649
42650           this.getTitle = function(index) {
42651             if (index >= this.titles.length) {
42652               return index + 1;
42653             }
42654
42655             return this.titles[index];
42656           };
42657
42658           $scope.rate = function(value) {
42659             if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {
42660 <<<<<<< HEAD
42661               var newViewValue = self.enableReset && ngModelCtrl.$viewValue === value ? 0 : value;
42662               ngModelCtrl.$setViewValue(newViewValue);
42663 =======
42664               ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value);
42665 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42666               ngModelCtrl.$render();
42667             }
42668           };
42669
42670           $scope.enter = function(value) {
42671             if (!$scope.readonly) {
42672               $scope.value = value;
42673             }
42674             $scope.onHover({value: value});
42675           };
42676
42677           $scope.reset = function() {
42678             $scope.value = ngModelCtrl.$viewValue;
42679             $scope.onLeave();
42680           };
42681
42682           $scope.onKeydown = function(evt) {
42683             if (/(37|38|39|40)/.test(evt.which)) {
42684               evt.preventDefault();
42685               evt.stopPropagation();
42686               $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));
42687             }
42688           };
42689
42690           this.render = function() {
42691             $scope.value = ngModelCtrl.$viewValue;
42692 <<<<<<< HEAD
42693             $scope.title = self.getTitle($scope.value - 1);
42694 =======
42695 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42696           };
42697         }])
42698
42699         .directive('uibRating', function() {
42700           return {
42701             require: ['uibRating', 'ngModel'],
42702             scope: {
42703 <<<<<<< HEAD
42704               readonly: '=?readOnly',
42705 =======
42706               readonly: '=?',
42707 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42708               onHover: '&',
42709               onLeave: '&'
42710             },
42711             controller: 'UibRatingController',
42712             templateUrl: 'uib/template/rating/rating.html',
42713             replace: true,
42714             link: function(scope, element, attrs, ctrls) {
42715               var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
42716               ratingCtrl.init(ngModelCtrl);
42717             }
42718           };
42719         });
42720
42721         angular.module('ui.bootstrap.tabs', [])
42722
42723         .controller('UibTabsetController', ['$scope', function ($scope) {
42724           var ctrl = this,
42725 <<<<<<< HEAD
42726             oldIndex;
42727           ctrl.tabs = [];
42728
42729           ctrl.select = function(index, evt) {
42730             if (!destroyed) {
42731               var previousIndex = findTabIndex(oldIndex);
42732               var previousSelected = ctrl.tabs[previousIndex];
42733               if (previousSelected) {
42734                 previousSelected.tab.onDeselect({
42735                   $event: evt,
42736                   $selectedIndex: index
42737                 });
42738                 if (evt && evt.isDefaultPrevented()) {
42739                   return;
42740                 }
42741                 previousSelected.tab.active = false;
42742               }
42743
42744               var selected = ctrl.tabs[index];
42745               if (selected) {
42746                 selected.tab.onSelect({
42747                   $event: evt
42748                 });
42749                 selected.tab.active = true;
42750                 ctrl.active = selected.index;
42751                 oldIndex = selected.index;
42752               } else if (!selected && angular.isDefined(oldIndex)) {
42753                 ctrl.active = null;
42754                 oldIndex = null;
42755               }
42756 =======
42757               tabs = ctrl.tabs = $scope.tabs = [];
42758
42759           ctrl.select = function(selectedTab) {
42760             angular.forEach(tabs, function(tab) {
42761               if (tab.active && tab !== selectedTab) {
42762                 tab.active = false;
42763                 tab.onDeselect();
42764                 selectedTab.selectCalled = false;
42765               }
42766             });
42767             selectedTab.active = true;
42768             // only call select if it has not already been called
42769             if (!selectedTab.selectCalled) {
42770               selectedTab.onSelect();
42771               selectedTab.selectCalled = true;
42772 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42773             }
42774           };
42775
42776           ctrl.addTab = function addTab(tab) {
42777 <<<<<<< HEAD
42778             ctrl.tabs.push({
42779               tab: tab,
42780               index: tab.index
42781             });
42782             ctrl.tabs.sort(function(t1, t2) {
42783               if (t1.index > t2.index) {
42784                 return 1;
42785               }
42786
42787               if (t1.index < t2.index) {
42788                 return -1;
42789               }
42790
42791               return 0;
42792             });
42793
42794             if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
42795               var newActiveIndex = findTabIndex(tab.index);
42796               ctrl.select(newActiveIndex);
42797 =======
42798             tabs.push(tab);
42799             // we can't run the select function on the first tab
42800             // since that would select it twice
42801             if (tabs.length === 1 && tab.active !== false) {
42802               tab.active = true;
42803             } else if (tab.active) {
42804               ctrl.select(tab);
42805             } else {
42806               tab.active = false;
42807 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42808             }
42809           };
42810
42811           ctrl.removeTab = function removeTab(tab) {
42812 <<<<<<< HEAD
42813             var index;
42814             for (var i = 0; i < ctrl.tabs.length; i++) {
42815               if (ctrl.tabs[i].tab === tab) {
42816                 index = i;
42817                 break;
42818               }
42819             }
42820
42821             if (ctrl.tabs[index].index === ctrl.active) {
42822               var newActiveTabIndex = index === ctrl.tabs.length - 1 ?
42823                 index - 1 : index + 1 % ctrl.tabs.length;
42824               ctrl.select(newActiveTabIndex);
42825             }
42826
42827             ctrl.tabs.splice(index, 1);
42828           };
42829
42830           $scope.$watch('tabset.active', function(val) {
42831             if (angular.isDefined(val) && val !== oldIndex) {
42832               ctrl.select(findTabIndex(val));
42833             }
42834           });
42835
42836 =======
42837             var index = tabs.indexOf(tab);
42838             //Select a new tab if the tab to be removed is selected and not destroyed
42839             if (tab.active && tabs.length > 1 && !destroyed) {
42840               //If this is the last tab, select the previous tab. else, the next tab.
42841               var newActiveIndex = index === tabs.length - 1 ? index - 1 : index + 1;
42842               ctrl.select(tabs[newActiveIndex]);
42843             }
42844             tabs.splice(index, 1);
42845           };
42846
42847 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42848           var destroyed;
42849           $scope.$on('$destroy', function() {
42850             destroyed = true;
42851           });
42852 <<<<<<< HEAD
42853
42854           function findTabIndex(index) {
42855             for (var i = 0; i < ctrl.tabs.length; i++) {
42856               if (ctrl.tabs[i].index === index) {
42857                 return i;
42858               }
42859             }
42860           }
42861 =======
42862 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42863         }])
42864
42865         .directive('uibTabset', function() {
42866           return {
42867             transclude: true,
42868             replace: true,
42869 <<<<<<< HEAD
42870             scope: {},
42871             bindToController: {
42872               active: '=?',
42873               type: '@'
42874             },
42875             controller: 'UibTabsetController',
42876             controllerAs: 'tabset',
42877             templateUrl: function(element, attrs) {
42878               return attrs.templateUrl || 'uib/template/tabs/tabset.html';
42879             },
42880             link: function(scope, element, attrs) {
42881               scope.vertical = angular.isDefined(attrs.vertical) ?
42882                 scope.$parent.$eval(attrs.vertical) : false;
42883               scope.justified = angular.isDefined(attrs.justified) ?
42884                 scope.$parent.$eval(attrs.justified) : false;
42885 =======
42886             scope: {
42887               type: '@'
42888             },
42889             controller: 'UibTabsetController',
42890             templateUrl: 'uib/template/tabs/tabset.html',
42891             link: function(scope, element, attrs) {
42892               scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;
42893               scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;
42894 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42895             }
42896           };
42897         })
42898
42899         .directive('uibTab', ['$parse', function($parse) {
42900           return {
42901             require: '^uibTabset',
42902             replace: true,
42903 <<<<<<< HEAD
42904             templateUrl: function(element, attrs) {
42905               return attrs.templateUrl || 'uib/template/tabs/tab.html';
42906             },
42907             transclude: true,
42908             scope: {
42909               heading: '@',
42910               index: '=?',
42911               classes: '@?',
42912 =======
42913             templateUrl: 'uib/template/tabs/tab.html',
42914             transclude: true,
42915             scope: {
42916               active: '=?',
42917               heading: '@',
42918 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42919               onSelect: '&select', //This callback is called in contentHeadingTransclude
42920                                   //once it inserts the tab's content into the dom
42921               onDeselect: '&deselect'
42922             },
42923             controller: function() {
42924               //Empty controller so other directives can require being 'under' a tab
42925             },
42926             controllerAs: 'tab',
42927             link: function(scope, elm, attrs, tabsetCtrl, transclude) {
42928 <<<<<<< HEAD
42929 =======
42930               scope.$watch('active', function(active) {
42931                 if (active) {
42932                   tabsetCtrl.select(scope);
42933                 }
42934               });
42935
42936 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42937               scope.disabled = false;
42938               if (attrs.disable) {
42939                 scope.$parent.$watch($parse(attrs.disable), function(value) {
42940                   scope.disabled = !! value;
42941                 });
42942               }
42943
42944 <<<<<<< HEAD
42945               if (angular.isUndefined(attrs.index)) {
42946                 if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {
42947                   scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function(t) { return t.index; })) + 1;
42948                 } else {
42949                   scope.index = 0;
42950                 }
42951               }
42952
42953               if (angular.isUndefined(attrs.classes)) {
42954                 scope.classes = '';
42955               }
42956
42957               scope.select = function(evt) {
42958                 if (!scope.disabled) {
42959                   var index;
42960                   for (var i = 0; i < tabsetCtrl.tabs.length; i++) {
42961                     if (tabsetCtrl.tabs[i].tab === scope) {
42962                       index = i;
42963                       break;
42964                     }
42965                   }
42966
42967                   tabsetCtrl.select(index, evt);
42968 =======
42969               scope.select = function() {
42970                 if (!scope.disabled) {
42971                   scope.active = true;
42972 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
42973                 }
42974               };
42975
42976               tabsetCtrl.addTab(scope);
42977               scope.$on('$destroy', function() {
42978                 tabsetCtrl.removeTab(scope);
42979               });
42980
42981               //We need to transclude later, once the content container is ready.
42982               //when this link happens, we're inside a tab heading.
42983               scope.$transcludeFn = transclude;
42984             }
42985           };
42986         }])
42987
42988         .directive('uibTabHeadingTransclude', function() {
42989           return {
42990             restrict: 'A',
42991             require: '^uibTab',
42992             link: function(scope, elm) {
42993               scope.$watch('headingElement', function updateHeadingElement(heading) {
42994                 if (heading) {
42995                   elm.html('');
42996                   elm.append(heading);
42997                 }
42998               });
42999             }
43000           };
43001         })
43002
43003         .directive('uibTabContentTransclude', function() {
43004           return {
43005             restrict: 'A',
43006             require: '^uibTabset',
43007             link: function(scope, elm, attrs) {
43008 <<<<<<< HEAD
43009               var tab = scope.$eval(attrs.uibTabContentTransclude).tab;
43010 =======
43011               var tab = scope.$eval(attrs.uibTabContentTransclude);
43012 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43013
43014               //Now our tab is ready to be transcluded: both the tab heading area
43015               //and the tab content area are loaded.  Transclude 'em both.
43016               tab.$transcludeFn(tab.$parent, function(contents) {
43017                 angular.forEach(contents, function(node) {
43018                   if (isTabHeading(node)) {
43019                     //Let tabHeadingTransclude know.
43020                     tab.headingElement = node;
43021                   } else {
43022                     elm.append(node);
43023                   }
43024                 });
43025               });
43026             }
43027           };
43028
43029           function isTabHeading(node) {
43030             return node.tagName && (
43031               node.hasAttribute('uib-tab-heading') ||
43032               node.hasAttribute('data-uib-tab-heading') ||
43033               node.hasAttribute('x-uib-tab-heading') ||
43034               node.tagName.toLowerCase() === 'uib-tab-heading' ||
43035               node.tagName.toLowerCase() === 'data-uib-tab-heading' ||
43036 <<<<<<< HEAD
43037               node.tagName.toLowerCase() === 'x-uib-tab-heading' ||
43038               node.tagName.toLowerCase() === 'uib:tab-heading'
43039 =======
43040               node.tagName.toLowerCase() === 'x-uib-tab-heading'
43041 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43042             );
43043           }
43044         });
43045
43046         angular.module('ui.bootstrap.timepicker', [])
43047
43048         .constant('uibTimepickerConfig', {
43049           hourStep: 1,
43050           minuteStep: 1,
43051           secondStep: 1,
43052           showMeridian: true,
43053           showSeconds: false,
43054           meridians: null,
43055           readonlyInput: false,
43056           mousewheel: true,
43057           arrowkeys: true,
43058 <<<<<<< HEAD
43059           showSpinners: true,
43060           templateUrl: 'uib/template/timepicker/timepicker.html'
43061 =======
43062           showSpinners: true
43063 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43064         })
43065
43066         .controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
43067           var selected = new Date(),
43068 <<<<<<< HEAD
43069             watchers = [],
43070             ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
43071             meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS,
43072             padHours = angular.isDefined($attrs.padHours) ? $scope.$parent.$eval($attrs.padHours) : true;
43073 =======
43074               ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
43075               meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;
43076 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43077
43078           $scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;
43079           $element.removeAttr('tabindex');
43080
43081           this.init = function(ngModelCtrl_, inputs) {
43082             ngModelCtrl = ngModelCtrl_;
43083             ngModelCtrl.$render = this.render;
43084
43085             ngModelCtrl.$formatters.unshift(function(modelValue) {
43086               return modelValue ? new Date(modelValue) : null;
43087             });
43088
43089             var hoursInputEl = inputs.eq(0),
43090                 minutesInputEl = inputs.eq(1),
43091                 secondsInputEl = inputs.eq(2);
43092
43093             var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;
43094
43095             if (mousewheel) {
43096               this.setupMousewheelEvents(hoursInputEl, minutesInputEl, secondsInputEl);
43097             }
43098
43099             var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;
43100             if (arrowkeys) {
43101               this.setupArrowkeyEvents(hoursInputEl, minutesInputEl, secondsInputEl);
43102             }
43103
43104             $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
43105             this.setupInputEvents(hoursInputEl, minutesInputEl, secondsInputEl);
43106           };
43107
43108           var hourStep = timepickerConfig.hourStep;
43109           if ($attrs.hourStep) {
43110 <<<<<<< HEAD
43111             watchers.push($scope.$parent.$watch($parse($attrs.hourStep), function(value) {
43112               hourStep = +value;
43113             }));
43114 =======
43115             $scope.$parent.$watch($parse($attrs.hourStep), function(value) {
43116               hourStep = parseInt(value, 10);
43117             });
43118 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43119           }
43120
43121           var minuteStep = timepickerConfig.minuteStep;
43122           if ($attrs.minuteStep) {
43123 <<<<<<< HEAD
43124             watchers.push($scope.$parent.$watch($parse($attrs.minuteStep), function(value) {
43125               minuteStep = +value;
43126             }));
43127           }
43128
43129           var min;
43130           watchers.push($scope.$parent.$watch($parse($attrs.min), function(value) {
43131             var dt = new Date(value);
43132             min = isNaN(dt) ? undefined : dt;
43133           }));
43134
43135           var max;
43136           watchers.push($scope.$parent.$watch($parse($attrs.max), function(value) {
43137             var dt = new Date(value);
43138             max = isNaN(dt) ? undefined : dt;
43139           }));
43140
43141           var disabled = false;
43142           if ($attrs.ngDisabled) {
43143             watchers.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {
43144               disabled = value;
43145             }));
43146 =======
43147             $scope.$parent.$watch($parse($attrs.minuteStep), function(value) {
43148               minuteStep = parseInt(value, 10);
43149             });
43150           }
43151
43152           var min;
43153           $scope.$parent.$watch($parse($attrs.min), function(value) {
43154             var dt = new Date(value);
43155             min = isNaN(dt) ? undefined : dt;
43156           });
43157
43158           var max;
43159           $scope.$parent.$watch($parse($attrs.max), function(value) {
43160             var dt = new Date(value);
43161             max = isNaN(dt) ? undefined : dt;
43162           });
43163
43164           var disabled = false;
43165           if ($attrs.ngDisabled) {
43166             $scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {
43167               disabled = value;
43168             });
43169 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43170           }
43171
43172           $scope.noIncrementHours = function() {
43173             var incrementedSelected = addMinutes(selected, hourStep * 60);
43174             return disabled || incrementedSelected > max ||
43175               incrementedSelected < selected && incrementedSelected < min;
43176           };
43177
43178           $scope.noDecrementHours = function() {
43179             var decrementedSelected = addMinutes(selected, -hourStep * 60);
43180             return disabled || decrementedSelected < min ||
43181               decrementedSelected > selected && decrementedSelected > max;
43182           };
43183
43184           $scope.noIncrementMinutes = function() {
43185             var incrementedSelected = addMinutes(selected, minuteStep);
43186             return disabled || incrementedSelected > max ||
43187               incrementedSelected < selected && incrementedSelected < min;
43188           };
43189
43190           $scope.noDecrementMinutes = function() {
43191             var decrementedSelected = addMinutes(selected, -minuteStep);
43192             return disabled || decrementedSelected < min ||
43193               decrementedSelected > selected && decrementedSelected > max;
43194           };
43195
43196           $scope.noIncrementSeconds = function() {
43197             var incrementedSelected = addSeconds(selected, secondStep);
43198             return disabled || incrementedSelected > max ||
43199               incrementedSelected < selected && incrementedSelected < min;
43200           };
43201
43202           $scope.noDecrementSeconds = function() {
43203             var decrementedSelected = addSeconds(selected, -secondStep);
43204             return disabled || decrementedSelected < min ||
43205               decrementedSelected > selected && decrementedSelected > max;
43206           };
43207
43208           $scope.noToggleMeridian = function() {
43209             if (selected.getHours() < 12) {
43210               return disabled || addMinutes(selected, 12 * 60) > max;
43211             }
43212
43213             return disabled || addMinutes(selected, -12 * 60) < min;
43214           };
43215
43216           var secondStep = timepickerConfig.secondStep;
43217           if ($attrs.secondStep) {
43218 <<<<<<< HEAD
43219             watchers.push($scope.$parent.$watch($parse($attrs.secondStep), function(value) {
43220               secondStep = +value;
43221             }));
43222 =======
43223             $scope.$parent.$watch($parse($attrs.secondStep), function(value) {
43224               secondStep = parseInt(value, 10);
43225             });
43226 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43227           }
43228
43229           $scope.showSeconds = timepickerConfig.showSeconds;
43230           if ($attrs.showSeconds) {
43231 <<<<<<< HEAD
43232             watchers.push($scope.$parent.$watch($parse($attrs.showSeconds), function(value) {
43233               $scope.showSeconds = !!value;
43234             }));
43235 =======
43236             $scope.$parent.$watch($parse($attrs.showSeconds), function(value) {
43237               $scope.showSeconds = !!value;
43238             });
43239 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43240           }
43241
43242           // 12H / 24H mode
43243           $scope.showMeridian = timepickerConfig.showMeridian;
43244           if ($attrs.showMeridian) {
43245 <<<<<<< HEAD
43246             watchers.push($scope.$parent.$watch($parse($attrs.showMeridian), function(value) {
43247 =======
43248             $scope.$parent.$watch($parse($attrs.showMeridian), function(value) {
43249 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43250               $scope.showMeridian = !!value;
43251
43252               if (ngModelCtrl.$error.time) {
43253                 // Evaluate from template
43254                 var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
43255                 if (angular.isDefined(hours) && angular.isDefined(minutes)) {
43256                   selected.setHours(hours);
43257                   refresh();
43258                 }
43259               } else {
43260                 updateTemplate();
43261               }
43262 <<<<<<< HEAD
43263             }));
43264 =======
43265             });
43266 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43267           }
43268
43269           // Get $scope.hours in 24H mode if valid
43270           function getHoursFromTemplate() {
43271 <<<<<<< HEAD
43272             var hours = +$scope.hours;
43273             var valid = $scope.showMeridian ? hours > 0 && hours < 13 :
43274               hours >= 0 && hours < 24;
43275             if (!valid || $scope.hours === '') {
43276 =======
43277             var hours = parseInt($scope.hours, 10);
43278             var valid = $scope.showMeridian ? hours > 0 && hours < 13 :
43279               hours >= 0 && hours < 24;
43280             if (!valid) {
43281 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43282               return undefined;
43283             }
43284
43285             if ($scope.showMeridian) {
43286               if (hours === 12) {
43287                 hours = 0;
43288               }
43289               if ($scope.meridian === meridians[1]) {
43290                 hours = hours + 12;
43291               }
43292             }
43293             return hours;
43294           }
43295
43296           function getMinutesFromTemplate() {
43297 <<<<<<< HEAD
43298             var minutes = +$scope.minutes;
43299             var valid = minutes >= 0 && minutes < 60;
43300             if (!valid || $scope.minutes === '') {
43301               return undefined;
43302             }
43303             return minutes;
43304           }
43305
43306           function getSecondsFromTemplate() {
43307             var seconds = +$scope.seconds;
43308             return seconds >= 0 && seconds < 60 ? seconds : undefined;
43309           }
43310
43311           function pad(value, noPad) {
43312 =======
43313             var minutes = parseInt($scope.minutes, 10);
43314             return minutes >= 0 && minutes < 60 ? minutes : undefined;
43315           }
43316
43317           function getSecondsFromTemplate() {
43318             var seconds = parseInt($scope.seconds, 10);
43319             return seconds >= 0 && seconds < 60 ? seconds : undefined;
43320           }
43321
43322           function pad(value) {
43323 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43324             if (value === null) {
43325               return '';
43326             }
43327
43328 <<<<<<< HEAD
43329             return angular.isDefined(value) && value.toString().length < 2 && !noPad ?
43330 =======
43331             return angular.isDefined(value) && value.toString().length < 2 ?
43332 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43333               '0' + value : value.toString();
43334           }
43335
43336           // Respond on mousewheel spin
43337           this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
43338             var isScrollingUp = function(e) {
43339               if (e.originalEvent) {
43340                 e = e.originalEvent;
43341               }
43342               //pick correct delta variable depending on event
43343               var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY;
43344               return e.detail || delta > 0;
43345             };
43346
43347             hoursInputEl.bind('mousewheel wheel', function(e) {
43348               if (!disabled) {
43349                 $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
43350               }
43351               e.preventDefault();
43352             });
43353
43354             minutesInputEl.bind('mousewheel wheel', function(e) {
43355               if (!disabled) {
43356                 $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
43357               }
43358               e.preventDefault();
43359             });
43360
43361              secondsInputEl.bind('mousewheel wheel', function(e) {
43362               if (!disabled) {
43363                 $scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds());
43364               }
43365               e.preventDefault();
43366             });
43367           };
43368
43369           // Respond on up/down arrowkeys
43370           this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
43371             hoursInputEl.bind('keydown', function(e) {
43372               if (!disabled) {
43373                 if (e.which === 38) { // up
43374                   e.preventDefault();
43375                   $scope.incrementHours();
43376                   $scope.$apply();
43377                 } else if (e.which === 40) { // down
43378                   e.preventDefault();
43379                   $scope.decrementHours();
43380                   $scope.$apply();
43381                 }
43382               }
43383             });
43384
43385             minutesInputEl.bind('keydown', function(e) {
43386               if (!disabled) {
43387                 if (e.which === 38) { // up
43388                   e.preventDefault();
43389                   $scope.incrementMinutes();
43390                   $scope.$apply();
43391                 } else if (e.which === 40) { // down
43392                   e.preventDefault();
43393                   $scope.decrementMinutes();
43394                   $scope.$apply();
43395                 }
43396               }
43397             });
43398
43399             secondsInputEl.bind('keydown', function(e) {
43400               if (!disabled) {
43401                 if (e.which === 38) { // up
43402                   e.preventDefault();
43403                   $scope.incrementSeconds();
43404                   $scope.$apply();
43405                 } else if (e.which === 40) { // down
43406                   e.preventDefault();
43407                   $scope.decrementSeconds();
43408                   $scope.$apply();
43409                 }
43410               }
43411             });
43412           };
43413
43414           this.setupInputEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
43415             if ($scope.readonlyInput) {
43416               $scope.updateHours = angular.noop;
43417               $scope.updateMinutes = angular.noop;
43418               $scope.updateSeconds = angular.noop;
43419               return;
43420             }
43421
43422             var invalidate = function(invalidHours, invalidMinutes, invalidSeconds) {
43423               ngModelCtrl.$setViewValue(null);
43424               ngModelCtrl.$setValidity('time', false);
43425               if (angular.isDefined(invalidHours)) {
43426                 $scope.invalidHours = invalidHours;
43427               }
43428
43429               if (angular.isDefined(invalidMinutes)) {
43430                 $scope.invalidMinutes = invalidMinutes;
43431               }
43432
43433               if (angular.isDefined(invalidSeconds)) {
43434                 $scope.invalidSeconds = invalidSeconds;
43435               }
43436             };
43437
43438             $scope.updateHours = function() {
43439               var hours = getHoursFromTemplate(),
43440                 minutes = getMinutesFromTemplate();
43441
43442               ngModelCtrl.$setDirty();
43443
43444               if (angular.isDefined(hours) && angular.isDefined(minutes)) {
43445                 selected.setHours(hours);
43446                 selected.setMinutes(minutes);
43447                 if (selected < min || selected > max) {
43448                   invalidate(true);
43449                 } else {
43450                   refresh('h');
43451                 }
43452               } else {
43453                 invalidate(true);
43454               }
43455             };
43456
43457             hoursInputEl.bind('blur', function(e) {
43458               ngModelCtrl.$setTouched();
43459 <<<<<<< HEAD
43460               if (modelIsEmpty()) {
43461                 makeValid();
43462               } else if ($scope.hours === null || $scope.hours === '') {
43463                 invalidate(true);
43464               } else if (!$scope.invalidHours && $scope.hours < 10) {
43465                 $scope.$apply(function() {
43466                   $scope.hours = pad($scope.hours, !padHours);
43467 =======
43468               if ($scope.hours === null || $scope.hours === '') {
43469                 invalidate(true);
43470               } else if (!$scope.invalidHours && $scope.hours < 10) {
43471                 $scope.$apply(function() {
43472                   $scope.hours = pad($scope.hours);
43473 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43474                 });
43475               }
43476             });
43477
43478             $scope.updateMinutes = function() {
43479               var minutes = getMinutesFromTemplate(),
43480                 hours = getHoursFromTemplate();
43481
43482               ngModelCtrl.$setDirty();
43483
43484               if (angular.isDefined(minutes) && angular.isDefined(hours)) {
43485                 selected.setHours(hours);
43486                 selected.setMinutes(minutes);
43487                 if (selected < min || selected > max) {
43488                   invalidate(undefined, true);
43489                 } else {
43490                   refresh('m');
43491                 }
43492               } else {
43493                 invalidate(undefined, true);
43494               }
43495             };
43496
43497             minutesInputEl.bind('blur', function(e) {
43498               ngModelCtrl.$setTouched();
43499 <<<<<<< HEAD
43500               if (modelIsEmpty()) {
43501                 makeValid();
43502               } else if ($scope.minutes === null) {
43503 =======
43504               if ($scope.minutes === null) {
43505 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43506                 invalidate(undefined, true);
43507               } else if (!$scope.invalidMinutes && $scope.minutes < 10) {
43508                 $scope.$apply(function() {
43509                   $scope.minutes = pad($scope.minutes);
43510                 });
43511               }
43512             });
43513
43514             $scope.updateSeconds = function() {
43515               var seconds = getSecondsFromTemplate();
43516
43517               ngModelCtrl.$setDirty();
43518
43519               if (angular.isDefined(seconds)) {
43520                 selected.setSeconds(seconds);
43521                 refresh('s');
43522               } else {
43523                 invalidate(undefined, undefined, true);
43524               }
43525             };
43526
43527             secondsInputEl.bind('blur', function(e) {
43528 <<<<<<< HEAD
43529               if (modelIsEmpty()) {
43530                 makeValid();
43531               } else if (!$scope.invalidSeconds && $scope.seconds < 10) {
43532 =======
43533               if (!$scope.invalidSeconds && $scope.seconds < 10) {
43534 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43535                 $scope.$apply( function() {
43536                   $scope.seconds = pad($scope.seconds);
43537                 });
43538               }
43539             });
43540
43541           };
43542
43543           this.render = function() {
43544             var date = ngModelCtrl.$viewValue;
43545
43546             if (isNaN(date)) {
43547               ngModelCtrl.$setValidity('time', false);
43548               $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
43549             } else {
43550               if (date) {
43551                 selected = date;
43552               }
43553
43554               if (selected < min || selected > max) {
43555                 ngModelCtrl.$setValidity('time', false);
43556                 $scope.invalidHours = true;
43557                 $scope.invalidMinutes = true;
43558               } else {
43559                 makeValid();
43560               }
43561               updateTemplate();
43562             }
43563           };
43564
43565           // Call internally when we know that model is valid.
43566           function refresh(keyboardChange) {
43567             makeValid();
43568             ngModelCtrl.$setViewValue(new Date(selected));
43569             updateTemplate(keyboardChange);
43570           }
43571
43572           function makeValid() {
43573             ngModelCtrl.$setValidity('time', true);
43574             $scope.invalidHours = false;
43575             $scope.invalidMinutes = false;
43576             $scope.invalidSeconds = false;
43577           }
43578
43579           function updateTemplate(keyboardChange) {
43580             if (!ngModelCtrl.$modelValue) {
43581               $scope.hours = null;
43582               $scope.minutes = null;
43583               $scope.seconds = null;
43584               $scope.meridian = meridians[0];
43585             } else {
43586               var hours = selected.getHours(),
43587                 minutes = selected.getMinutes(),
43588                 seconds = selected.getSeconds();
43589
43590               if ($scope.showMeridian) {
43591                 hours = hours === 0 || hours === 12 ? 12 : hours % 12; // Convert 24 to 12 hour system
43592               }
43593
43594 <<<<<<< HEAD
43595               $scope.hours = keyboardChange === 'h' ? hours : pad(hours, !padHours);
43596 =======
43597               $scope.hours = keyboardChange === 'h' ? hours : pad(hours);
43598 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43599               if (keyboardChange !== 'm') {
43600                 $scope.minutes = pad(minutes);
43601               }
43602               $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
43603
43604               if (keyboardChange !== 's') {
43605                 $scope.seconds = pad(seconds);
43606               }
43607               $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
43608             }
43609           }
43610
43611           function addSecondsToSelected(seconds) {
43612             selected = addSeconds(selected, seconds);
43613             refresh();
43614           }
43615
43616           function addMinutes(selected, minutes) {
43617             return addSeconds(selected, minutes*60);
43618           }
43619
43620           function addSeconds(date, seconds) {
43621             var dt = new Date(date.getTime() + seconds * 1000);
43622             var newDate = new Date(date);
43623             newDate.setHours(dt.getHours(), dt.getMinutes(), dt.getSeconds());
43624             return newDate;
43625           }
43626
43627 <<<<<<< HEAD
43628           function modelIsEmpty() {
43629             return ($scope.hours === null || $scope.hours === '') &&
43630               ($scope.minutes === null || $scope.minutes === '') &&
43631               (!$scope.showSeconds || $scope.showSeconds && ($scope.seconds === null || $scope.seconds === ''));
43632           }
43633
43634 =======
43635 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43636           $scope.showSpinners = angular.isDefined($attrs.showSpinners) ?
43637             $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;
43638
43639           $scope.incrementHours = function() {
43640             if (!$scope.noIncrementHours()) {
43641               addSecondsToSelected(hourStep * 60 * 60);
43642             }
43643           };
43644
43645           $scope.decrementHours = function() {
43646             if (!$scope.noDecrementHours()) {
43647               addSecondsToSelected(-hourStep * 60 * 60);
43648             }
43649           };
43650
43651           $scope.incrementMinutes = function() {
43652             if (!$scope.noIncrementMinutes()) {
43653               addSecondsToSelected(minuteStep * 60);
43654             }
43655           };
43656
43657           $scope.decrementMinutes = function() {
43658             if (!$scope.noDecrementMinutes()) {
43659               addSecondsToSelected(-minuteStep * 60);
43660             }
43661           };
43662
43663           $scope.incrementSeconds = function() {
43664             if (!$scope.noIncrementSeconds()) {
43665               addSecondsToSelected(secondStep);
43666             }
43667           };
43668
43669           $scope.decrementSeconds = function() {
43670             if (!$scope.noDecrementSeconds()) {
43671               addSecondsToSelected(-secondStep);
43672             }
43673           };
43674
43675           $scope.toggleMeridian = function() {
43676             var minutes = getMinutesFromTemplate(),
43677                 hours = getHoursFromTemplate();
43678
43679             if (!$scope.noToggleMeridian()) {
43680               if (angular.isDefined(minutes) && angular.isDefined(hours)) {
43681                 addSecondsToSelected(12 * 60 * (selected.getHours() < 12 ? 60 : -60));
43682               } else {
43683                 $scope.meridian = $scope.meridian === meridians[0] ? meridians[1] : meridians[0];
43684               }
43685             }
43686           };
43687
43688           $scope.blur = function() {
43689             ngModelCtrl.$setTouched();
43690           };
43691 <<<<<<< HEAD
43692
43693           $scope.$on('$destroy', function() {
43694             while (watchers.length) {
43695               watchers.shift()();
43696             }
43697           });
43698         }])
43699
43700         .directive('uibTimepicker', ['uibTimepickerConfig', function(uibTimepickerConfig) {
43701 =======
43702         }])
43703
43704         .directive('uibTimepicker', function() {
43705 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43706           return {
43707             require: ['uibTimepicker', '?^ngModel'],
43708             controller: 'UibTimepickerController',
43709             controllerAs: 'timepicker',
43710             replace: true,
43711             scope: {},
43712             templateUrl: function(element, attrs) {
43713 <<<<<<< HEAD
43714               return attrs.templateUrl || uibTimepickerConfig.templateUrl;
43715 =======
43716               return attrs.templateUrl || 'uib/template/timepicker/timepicker.html';
43717 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43718             },
43719             link: function(scope, element, attrs, ctrls) {
43720               var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
43721
43722               if (ngModelCtrl) {
43723                 timepickerCtrl.init(ngModelCtrl, element.find('input'));
43724               }
43725             }
43726           };
43727 <<<<<<< HEAD
43728         }]);
43729 =======
43730         });
43731 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43732
43733         angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap.position'])
43734
43735         /**
43736          * A helper service that can parse typeahead's syntax (string provided by users)
43737          * Extracted to a separate service for ease of unit testing
43738          */
43739           .factory('uibTypeaheadParser', ['$parse', function($parse) {
43740             //                      00000111000000000000022200000000000000003333333333333330000000000044000
43741             var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
43742             return {
43743               parse: function(input) {
43744                 var match = input.match(TYPEAHEAD_REGEXP);
43745                 if (!match) {
43746                   throw new Error(
43747                     'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' +
43748                       ' but got "' + input + '".');
43749                 }
43750
43751                 return {
43752                   itemName: match[3],
43753                   source: $parse(match[4]),
43754                   viewMapper: $parse(match[2] || match[1]),
43755                   modelMapper: $parse(match[1])
43756                 };
43757               }
43758             };
43759           }])
43760
43761           .controller('UibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$$debounce', '$uibPosition', 'uibTypeaheadParser',
43762             function(originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $$debounce, $position, typeaheadParser) {
43763             var HOT_KEYS = [9, 13, 27, 38, 40];
43764             var eventDebounceTime = 200;
43765             var modelCtrl, ngModelOptions;
43766             //SUPPORTED ATTRIBUTES (OPTIONS)
43767
43768             //minimal no of characters that needs to be entered before typeahead kicks-in
43769             var minLength = originalScope.$eval(attrs.typeaheadMinLength);
43770             if (!minLength && minLength !== 0) {
43771               minLength = 1;
43772             }
43773
43774 <<<<<<< HEAD
43775             originalScope.$watch(attrs.typeaheadMinLength, function (newVal) {
43776                 minLength = !newVal && newVal !== 0 ? 1 : newVal;
43777             });
43778
43779 =======
43780 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43781             //minimal wait time after last character typed before typeahead kicks-in
43782             var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
43783
43784             //should it restrict model values to the ones selected from the popup only?
43785             var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
43786             originalScope.$watch(attrs.typeaheadEditable, function (newVal) {
43787               isEditable = newVal !== false;
43788             });
43789
43790             //binding to a variable that indicates if matches are being retrieved asynchronously
43791             var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
43792
43793 <<<<<<< HEAD
43794             //a function to determine if an event should cause selection
43795             var isSelectEvent = attrs.typeaheadShouldSelect ? $parse(attrs.typeaheadShouldSelect) : function(scope, vals) {
43796               var evt = vals.$event;
43797               return evt.which === 13 || evt.which === 9;
43798             };
43799
43800 =======
43801 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43802             //a callback executed when a match is selected
43803             var onSelectCallback = $parse(attrs.typeaheadOnSelect);
43804
43805             //should it select highlighted popup value when losing focus?
43806             var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;
43807
43808             //binding to a variable that indicates if there were no results after the query is completed
43809             var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;
43810
43811             var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;
43812
43813             var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;
43814
43815             var appendTo = attrs.typeaheadAppendTo ?
43816               originalScope.$eval(attrs.typeaheadAppendTo) : null;
43817
43818             var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;
43819
43820             //If input matches an item of the list exactly, select it automatically
43821             var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;
43822
43823             //binding to a variable that indicates if dropdown is open
43824             var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;
43825
43826             var showHint = originalScope.$eval(attrs.typeaheadShowHint) || false;
43827
43828             //INTERNAL VARIABLES
43829
43830             //model setter executed upon match selection
43831             var parsedModel = $parse(attrs.ngModel);
43832             var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');
43833             var $setModelValue = function(scope, newValue) {
43834               if (angular.isFunction(parsedModel(originalScope)) &&
43835                 ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) {
43836                 return invokeModelSetter(scope, {$$$p: newValue});
43837               }
43838
43839               return parsedModel.assign(scope, newValue);
43840             };
43841
43842             //expressions used by typeahead
43843             var parserResult = typeaheadParser.parse(attrs.uibTypeahead);
43844
43845             var hasFocus;
43846
43847             //Used to avoid bug in iOS webview where iOS keyboard does not fire
43848             //mousedown & mouseup events
43849             //Issue #3699
43850             var selected;
43851
43852             //create a child scope for the typeahead directive so we are not polluting original scope
43853             //with typeahead-specific data (matches, query etc.)
43854             var scope = originalScope.$new();
43855             var offDestroy = originalScope.$on('$destroy', function() {
43856               scope.$destroy();
43857             });
43858             scope.$on('$destroy', offDestroy);
43859
43860             // WAI-ARIA
43861             var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
43862             element.attr({
43863               'aria-autocomplete': 'list',
43864               'aria-expanded': false,
43865               'aria-owns': popupId
43866             });
43867
43868             var inputsContainer, hintInputElem;
43869             //add read-only input to show hint
43870             if (showHint) {
43871               inputsContainer = angular.element('<div></div>');
43872               inputsContainer.css('position', 'relative');
43873               element.after(inputsContainer);
43874               hintInputElem = element.clone();
43875               hintInputElem.attr('placeholder', '');
43876 <<<<<<< HEAD
43877               hintInputElem.attr('tabindex', '-1');
43878 =======
43879 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
43880               hintInputElem.val('');
43881               hintInputElem.css({
43882                 'position': 'absolute',
43883                 'top': '0px',
43884                 'left': '0px',
43885                 'border-color': 'transparent',
43886                 'box-shadow': 'none',
43887                 'opacity': 1,
43888                 'background': 'none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)',
43889                 'color': '#999'
43890               });
43891               element.css({
43892                 'position': 'relative',
43893                 'vertical-align': 'top',
43894                 'background-color': 'transparent'
43895               });
43896               inputsContainer.append(hintInputElem);
43897               hintInputElem.after(element);
43898             }
43899
43900             //pop-up element used to display matches
43901             var popUpEl = angular.element('<div uib-typeahead-popup></div>');
43902             popUpEl.attr({
43903               id: popupId,
43904               matches: 'matches',
43905               active: 'activeIdx',
43906               select: 'select(activeIdx, evt)',
43907               'move-in-progress': 'moveInProgress',
43908               query: 'query',
43909               position: 'position',
43910               'assign-is-open': 'assignIsOpen(isOpen)',
43911               debounce: 'debounceUpdate'
43912             });
43913             //custom item template
43914             if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
43915               popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
43916             }
43917
43918             if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {
43919               popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);
43920             }
43921
43922             var resetHint = function() {
43923               if (showHint) {
43924                 hintInputElem.val('');
43925               }
43926             };
43927
43928             var resetMatches = function() {
43929               scope.matches = [];
43930               scope.activeIdx = -1;
43931               element.attr('aria-expanded', false);
43932               resetHint();
43933             };
43934
43935             var getMatchId = function(index) {
43936               return popupId + '-option-' + index;
43937             };
43938
43939             // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.
43940             // This attribute is added or removed automatically when the `activeIdx` changes.
43941             scope.$watch('activeIdx', function(index) {
43942               if (index < 0) {
43943                 element.removeAttr('aria-activedescendant');
43944               } else {
43945                 element.attr('aria-activedescendant', getMatchId(index));
43946               }
43947             });
43948
43949             var inputIsExactMatch = function(inputValue, index) {
43950               if (scope.matches.length > index && inputValue) {
43951                 return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();
43952               }
43953
43954               return false;
43955             };
43956
43957             var getMatchesAsync = function(inputValue, evt) {
43958               var locals = {$viewValue: inputValue};
43959               isLoadingSetter(originalScope, true);
43960               isNoResultsSetter(originalScope, false);
43961               $q.when(parserResult.source(originalScope, locals)).then(function(matches) {
43962                 //it might happen that several async queries were in progress if a user were typing fast
43963                 //but we are interested only in responses that correspond to the current view value
43964                 var onCurrentRequest = inputValue === modelCtrl.$viewValue;
43965                 if (onCurrentRequest && hasFocus) {
43966                   if (matches && matches.length > 0) {
43967                     scope.activeIdx = focusFirst ? 0 : -1;
43968                     isNoResultsSetter(originalScope, false);
43969                     scope.matches.length = 0;
43970
43971                     //transform labels
43972                     for (var i = 0; i < matches.length; i++) {
43973                       locals[parserResult.itemName] = matches[i];
43974                       scope.matches.push({
43975                         id: getMatchId(i),
43976                         label: parserResult.viewMapper(scope, locals),
43977                         model: matches[i]
43978                       });
43979                     }
43980
43981                     scope.query = inputValue;
43982                     //position pop-up with matches - we need to re-calculate its position each time we are opening a window
43983                     //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
43984                     //due to other elements being rendered
43985                     recalculatePosition();
43986
43987                     element.attr('aria-expanded', true);
43988
43989                     //Select the single remaining option if user input matches
43990                     if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {
43991                       if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
43992                         $$debounce(function() {
43993                           scope.select(0, evt);
43994                         }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
43995                       } else {
43996                         scope.select(0, evt);
43997                       }
43998                     }
43999
44000                     if (showHint) {
44001                       var firstLabel = scope.matches[0].label;
44002 <<<<<<< HEAD
44003                       if (angular.isString(inputValue) &&
44004                         inputValue.length > 0 &&
44005                         firstLabel.slice(0, inputValue.length).toUpperCase() === inputValue.toUpperCase()) {
44006                         hintInputElem.val(inputValue + firstLabel.slice(inputValue.length));
44007                       } else {
44008 =======
44009                       if (inputValue.length > 0 && firstLabel.slice(0, inputValue.length).toUpperCase() === inputValue.toUpperCase()) {
44010                         hintInputElem.val(inputValue + firstLabel.slice(inputValue.length));
44011                       }
44012                       else {
44013 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
44014                         hintInputElem.val('');
44015                       }
44016                     }
44017                   } else {
44018                     resetMatches();
44019                     isNoResultsSetter(originalScope, true);
44020                   }
44021                 }
44022                 if (onCurrentRequest) {
44023                   isLoadingSetter(originalScope, false);
44024                 }
44025               }, function() {
44026                 resetMatches();
44027                 isLoadingSetter(originalScope, false);
44028                 isNoResultsSetter(originalScope, true);
44029               });
44030             };
44031
44032             // bind events only if appendToBody params exist - performance feature
44033             if (appendToBody) {
44034               angular.element($window).on('resize', fireRecalculating);
44035               $document.find('body').on('scroll', fireRecalculating);
44036             }
44037
44038             // Declare the debounced function outside recalculating for
44039             // proper debouncing
44040             var debouncedRecalculate = $$debounce(function() {
44041               // if popup is visible
44042               if (scope.matches.length) {
44043                 recalculatePosition();
44044               }
44045
44046               scope.moveInProgress = false;
44047             }, eventDebounceTime);
44048
44049             // Default progress type
44050             scope.moveInProgress = false;
44051
44052             function fireRecalculating() {
44053               if (!scope.moveInProgress) {
44054                 scope.moveInProgress = true;
44055                 scope.$digest();
44056               }
44057
44058               debouncedRecalculate();
44059             }
44060
44061             // recalculate actual position and set new values to scope
44062             // after digest loop is popup in right position
44063             function recalculatePosition() {
44064               scope.position = appendToBody ? $position.offset(element) : $position.position(element);
44065               scope.position.top += element.prop('offsetHeight');
44066             }
44067
44068             //we need to propagate user's query so we can higlight matches
44069             scope.query = undefined;
44070
44071             //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
44072             var timeoutPromise;
44073
44074             var scheduleSearchWithTimeout = function(inputValue) {
44075               timeoutPromise = $timeout(function() {
44076                 getMatchesAsync(inputValue);
44077               }, waitTime);
44078             };
44079
44080             var cancelPreviousTimeout = function() {
44081               if (timeoutPromise) {
44082                 $timeout.cancel(timeoutPromise);
44083               }
44084             };
44085
44086             resetMatches();
44087
44088             scope.assignIsOpen = function (isOpen) {
44089               isOpenSetter(originalScope, isOpen);
44090             };
44091
44092             scope.select = function(activeIdx, evt) {
44093               //called from within the $digest() cycle
44094               var locals = {};
44095               var model, item;
44096
44097               selected = true;
44098               locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
44099               model = parserResult.modelMapper(originalScope, locals);
44100               $setModelValue(originalScope, model);
44101               modelCtrl.$setValidity('editable', true);
44102               modelCtrl.$setValidity('parse', true);
44103
44104               onSelectCallback(originalScope, {
44105                 $item: item,
44106                 $model: model,
44107                 $label: parserResult.viewMapper(originalScope, locals),
44108                 $event: evt
44109               });
44110
44111               resetMatches();
44112
44113               //return focus to the input element if a match was selected via a mouse click event
44114               // use timeout to avoid $rootScope:inprog error
44115               if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {
44116                 $timeout(function() { element[0].focus(); }, 0, false);
44117               }
44118             };
44119
44120             //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
44121             element.on('keydown', function(evt) {
44122               //typeahead is open and an "interesting" key was pressed
44123               if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
44124                 return;
44125               }
44126
44127 <<<<<<< HEAD
44128               var shouldSelect = isSelectEvent(originalScope, {$event: evt});
44129
44130               /**
44131                * if there's nothing selected (i.e. focusFirst) and enter or tab is hit
44132                * or
44133                * shift + tab is pressed to bring focus to the previous element
44134                * then clear the results
44135                */
44136               if (scope.activeIdx === -1 && shouldSelect || evt.which === 9 && !!evt.shiftKey) {
44137 =======
44138               // if there's nothing selected (i.e. focusFirst) and enter or tab is hit, clear the results
44139               if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) {
44140 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
44141                 resetMatches();
44142                 scope.$digest();
44143                 return;
44144               }
44145
44146               evt.preventDefault();
44147 <<<<<<< HEAD
44148               var target;
44149               switch (evt.which) {
44150                 case 27: // escape
44151                   evt.stopPropagation();
44152
44153                   resetMatches();
44154                   originalScope.$digest();
44155                   break;
44156                 case 38: // up arrow
44157                   scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
44158                   scope.$digest();
44159                   target = popUpEl.find('li')[scope.activeIdx];
44160                   target.parentNode.scrollTop = target.offsetTop;
44161                   break;
44162                 case 40: // down arrow
44163                   scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
44164                   scope.$digest();
44165                   target = popUpEl.find('li')[scope.activeIdx];
44166                   target.parentNode.scrollTop = target.offsetTop;
44167                   break;
44168                 default:
44169                   if (shouldSelect) {
44170                     scope.$apply(function() {
44171                       if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
44172                         $$debounce(function() {
44173                           scope.select(scope.activeIdx, evt);
44174                         }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
44175                       } else {
44176                         scope.select(scope.activeIdx, evt);
44177                       }
44178                     });
44179                   }
44180 =======
44181
44182               switch (evt.which) {
44183                 case 9:
44184                 case 13:
44185                   scope.$apply(function () {
44186                     if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
44187                       $$debounce(function() {
44188                         scope.select(scope.activeIdx, evt);
44189                       }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
44190                     } else {
44191                       scope.select(scope.activeIdx, evt);
44192                     }
44193                   });
44194                   break;
44195                 case 27:
44196                   evt.stopPropagation();
44197
44198                   resetMatches();
44199                   scope.$digest();
44200                   break;
44201                 case 38:
44202                   scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
44203                   scope.$digest();
44204                   popUpEl.find('li')[scope.activeIdx].scrollIntoView(false);
44205                   break;
44206                 case 40:
44207                   scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
44208                   scope.$digest();
44209                   popUpEl.find('li')[scope.activeIdx].scrollIntoView(false);
44210                   break;
44211 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
44212               }
44213             });
44214
44215             element.bind('focus', function (evt) {
44216               hasFocus = true;
44217               if (minLength === 0 && !modelCtrl.$viewValue) {
44218                 $timeout(function() {
44219                   getMatchesAsync(modelCtrl.$viewValue, evt);
44220                 }, 0);
44221               }
44222             });
44223
44224             element.bind('blur', function(evt) {
44225               if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {
44226                 selected = true;
44227                 scope.$apply(function() {
44228                   if (angular.isObject(scope.debounceUpdate) && angular.isNumber(scope.debounceUpdate.blur)) {
44229                     $$debounce(function() {
44230                       scope.select(scope.activeIdx, evt);
44231                     }, scope.debounceUpdate.blur);
44232                   } else {
44233                     scope.select(scope.activeIdx, evt);
44234                   }
44235                 });
44236               }
44237               if (!isEditable && modelCtrl.$error.editable) {
44238 <<<<<<< HEAD
44239                 modelCtrl.$setViewValue();
44240                 // Reset validity as we are clearing
44241                 modelCtrl.$setValidity('editable', true);
44242                 modelCtrl.$setValidity('parse', true);
44243 =======
44244                 modelCtrl.$viewValue = '';
44245 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
44246                 element.val('');
44247               }
44248               hasFocus = false;
44249               selected = false;
44250             });
44251
44252             // Keep reference to click handler to unbind it.
44253             var dismissClickHandler = function(evt) {
44254               // Issue #3973
44255               // Firefox treats right click as a click on document
44256               if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {
44257                 resetMatches();
44258                 if (!$rootScope.$$phase) {
44259 <<<<<<< HEAD
44260                   originalScope.$digest();
44261 =======
44262                   scope.$digest();
44263 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
44264                 }
44265               }
44266             };
44267
44268             $document.on('click', dismissClickHandler);
44269
44270             originalScope.$on('$destroy', function() {
44271               $document.off('click', dismissClickHandler);
44272               if (appendToBody || appendTo) {
44273                 $popup.remove();
44274               }
44275
44276               if (appendToBody) {
44277                 angular.element($window).off('resize', fireRecalculating);
44278                 $document.find('body').off('scroll', fireRecalculating);
44279               }
44280               // Prevent jQuery cache memory leak
44281               popUpEl.remove();
44282
44283               if (showHint) {
44284                   inputsContainer.remove();
44285               }
44286             });
44287
44288             var $popup = $compile(popUpEl)(scope);
44289
44290             if (appendToBody) {
44291               $document.find('body').append($popup);
44292             } else if (appendTo) {
44293               angular.element(appendTo).eq(0).append($popup);
44294             } else {
44295               element.after($popup);
44296             }
44297
44298             this.init = function(_modelCtrl, _ngModelOptions) {
44299               modelCtrl = _modelCtrl;
44300               ngModelOptions = _ngModelOptions;
44301
44302               scope.debounceUpdate = modelCtrl.$options && $parse(modelCtrl.$options.debounce)(originalScope);
44303
44304               //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
44305               //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
44306               modelCtrl.$parsers.unshift(function(inputValue) {
44307                 hasFocus = true;
44308
44309                 if (minLength === 0 || inputValue && inputValue.length >= minLength) {
44310                   if (waitTime > 0) {
44311                     cancelPreviousTimeout();
44312                     scheduleSearchWithTimeout(inputValue);
44313                   } else {
44314                     getMatchesAsync(inputValue);
44315                   }
44316                 } else {
44317                   isLoadingSetter(originalScope, false);
44318                   cancelPreviousTimeout();
44319                   resetMatches();
44320                 }
44321
44322                 if (isEditable) {
44323                   return inputValue;
44324                 }
44325
44326                 if (!inputValue) {
44327                   // Reset in case user had typed something previously.
44328                   modelCtrl.$setValidity('editable', true);
44329                   return null;
44330                 }
44331
44332                 modelCtrl.$setValidity('editable', false);
44333                 return undefined;
44334               });
44335
44336               modelCtrl.$formatters.push(function(modelValue) {
44337                 var candidateViewValue, emptyViewValue;
44338                 var locals = {};
44339
44340                 // The validity may be set to false via $parsers (see above) if
44341                 // the model is restricted to selected values. If the model
44342                 // is set manually it is considered to be valid.
44343                 if (!isEditable) {
44344                   modelCtrl.$setValidity('editable', true);
44345                 }
44346
44347                 if (inputFormatter) {
44348                   locals.$model = modelValue;
44349                   return inputFormatter(originalScope, locals);
44350                 }
44351
44352                 //it might happen that we don't have enough info to properly render input value
44353                 //we need to check for this situation and simply return model value if we can't apply custom formatting
44354                 locals[parserResult.itemName] = modelValue;
44355                 candidateViewValue = parserResult.viewMapper(originalScope, locals);
44356                 locals[parserResult.itemName] = undefined;
44357                 emptyViewValue = parserResult.viewMapper(originalScope, locals);
44358
44359                 return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;
44360               });
44361             };
44362           }])
44363
44364           .directive('uibTypeahead', function() {
44365             return {
44366               controller: 'UibTypeaheadController',
44367               require: ['ngModel', '^?ngModelOptions', 'uibTypeahead'],
44368               link: function(originalScope, element, attrs, ctrls) {
44369                 ctrls[2].init(ctrls[0], ctrls[1]);
44370               }
44371             };
44372           })
44373
44374           .directive('uibTypeaheadPopup', ['$$debounce', function($$debounce) {
44375             return {
44376               scope: {
44377                 matches: '=',
44378                 query: '=',
44379                 active: '=',
44380                 position: '&',
44381                 moveInProgress: '=',
44382                 select: '&',
44383                 assignIsOpen: '&',
44384                 debounce: '&'
44385               },
44386               replace: true,
44387               templateUrl: function(element, attrs) {
44388 <<<<<<< HEAD
44389                 return attrs.popupTemplateUrl || 'uib/template/typeahead/typeahead-popup.html';
44390               },
44391               link: function(scope, element, attrs) {
44392                 scope.templateUrl = attrs.templateUrl;
44393
44394                 scope.isOpen = function() {
44395                   var isDropdownOpen = scope.matches.length > 0;
44396                   scope.assignIsOpen({ isOpen: isDropdownOpen });
44397                   return isDropdownOpen;
44398                 };
44399
44400                 scope.isActive = function(matchIdx) {
44401                   return scope.active === matchIdx;
44402                 };
44403
44404                 scope.selectActive = function(matchIdx) {
44405                   scope.active = matchIdx;
44406                 };
44407
44408                 scope.selectMatch = function(activeIdx, evt) {
44409                   var debounce = scope.debounce();
44410                   if (angular.isNumber(debounce) || angular.isObject(debounce)) {
44411                     $$debounce(function() {
44412                       scope.select({activeIdx: activeIdx, evt: evt});
44413                     }, angular.isNumber(debounce) ? debounce : debounce['default']);
44414                   } else {
44415                     scope.select({activeIdx: activeIdx, evt: evt});
44416                   }
44417                 };
44418               }
44419             };
44420           }])
44421
44422           .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function($templateRequest, $compile, $parse) {
44423             return {
44424               scope: {
44425                 index: '=',
44426                 match: '=',
44427                 query: '='
44428               },
44429               link: function(scope, element, attrs) {
44430                 var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'uib/template/typeahead/typeahead-match.html';
44431                 $templateRequest(tplUrl).then(function(tplContent) {
44432                   var tplEl = angular.element(tplContent.trim());
44433                   element.replaceWith(tplEl);
44434                   $compile(tplEl)(scope);
44435                 });
44436               }
44437             };
44438           }])
44439
44440           .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function($sce, $injector, $log) {
44441             var isSanitizePresent;
44442             isSanitizePresent = $injector.has('$sanitize');
44443
44444             function escapeRegexp(queryToEscape) {
44445               // Regex: capture the whole query string and replace it with the string that will be used to match
44446               // the results, for example if the capture is "a" the result will be \a
44447               return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
44448             }
44449
44450             function containsHtml(matchItem) {
44451               return /<.*>/g.test(matchItem);
44452             }
44453
44454             return function(matchItem, query) {
44455               if (!isSanitizePresent && containsHtml(matchItem)) {
44456                 $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger
44457               }
44458               matchItem = query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem; // Replaces the capture string with a the same string inside of a "strong" tag
44459               if (!isSanitizePresent) {
44460                 matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive
44461               }
44462               return matchItem;
44463             };
44464           }]);
44465
44466         angular.module("uib/template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
44467           $templateCache.put("uib/template/accordion/accordion-group.html",
44468             "<div class=\"panel\" ng-class=\"panelClass || 'panel-default'\">\n" +
44469             "  <div role=\"tab\" id=\"{{::headingId}}\" aria-selected=\"{{isOpen}}\" class=\"panel-heading\" ng-keypress=\"toggleOpen($event)\">\n" +
44470             "    <h4 class=\"panel-title\">\n" +
44471             "      <a role=\"button\" data-toggle=\"collapse\" href aria-expanded=\"{{isOpen}}\" aria-controls=\"{{::panelId}}\" tabindex=\"0\" class=\"accordion-toggle\" ng-click=\"toggleOpen()\" uib-accordion-transclude=\"heading\"><span uib-accordion-header ng-class=\"{'text-muted': isDisabled}\">{{heading}}</span></a>\n" +
44472             "    </h4>\n" +
44473             "  </div>\n" +
44474             "  <div id=\"{{::panelId}}\" aria-labelledby=\"{{::headingId}}\" aria-hidden=\"{{!isOpen}}\" role=\"tabpanel\" class=\"panel-collapse collapse\" uib-collapse=\"!isOpen\">\n" +
44475             "    <div class=\"panel-body\" ng-transclude></div>\n" +
44476             "  </div>\n" +
44477             "</div>\n" +
44478             "");
44479         }]);
44480
44481         angular.module("uib/template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
44482           $templateCache.put("uib/template/accordion/accordion.html",
44483             "<div role=\"tablist\" class=\"panel-group\" ng-transclude></div>");
44484         }]);
44485
44486         angular.module("uib/template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
44487           $templateCache.put("uib/template/alert/alert.html",
44488             "<div class=\"alert\" ng-class=\"['alert-' + (type || 'warning'), closeable ? 'alert-dismissible' : null]\" role=\"alert\">\n" +
44489             "    <button ng-show=\"closeable\" type=\"button\" class=\"close\" ng-click=\"close({$event: $event})\">\n" +
44490             "        <span aria-hidden=\"true\">&times;</span>\n" +
44491             "        <span class=\"sr-only\">Close</span>\n" +
44492             "    </button>\n" +
44493             "    <div ng-transclude></div>\n" +
44494             "</div>\n" +
44495             "");
44496         }]);
44497
44498         angular.module("uib/template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
44499           $templateCache.put("uib/template/carousel/carousel.html",
44500             "<div ng-mouseenter=\"pause()\" ng-mouseleave=\"play()\" class=\"carousel\" ng-swipe-right=\"prev()\" ng-swipe-left=\"next()\">\n" +
44501             "  <div class=\"carousel-inner\" ng-transclude></div>\n" +
44502             "  <a role=\"button\" href class=\"left carousel-control\" ng-click=\"prev()\" ng-class=\"{ disabled: isPrevDisabled() }\" ng-show=\"slides.length > 1\">\n" +
44503             "    <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></span>\n" +
44504             "    <span class=\"sr-only\">previous</span>\n" +
44505             "  </a>\n" +
44506             "  <a role=\"button\" href class=\"right carousel-control\" ng-click=\"next()\" ng-class=\"{ disabled: isNextDisabled() }\" ng-show=\"slides.length > 1\">\n" +
44507             "    <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></span>\n" +
44508             "    <span class=\"sr-only\">next</span>\n" +
44509             "  </a>\n" +
44510             "  <ol class=\"carousel-indicators\" ng-show=\"slides.length > 1\">\n" +
44511             "    <li ng-repeat=\"slide in slides | orderBy:indexOfSlide track by $index\" ng-class=\"{ active: isActive(slide) }\" ng-click=\"select(slide)\">\n" +
44512             "      <span class=\"sr-only\">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if=\"isActive(slide)\">, currently active</span></span>\n" +
44513             "    </li>\n" +
44514             "  </ol>\n" +
44515             "</div>\n" +
44516             "");
44517         }]);
44518
44519         angular.module("uib/template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
44520           $templateCache.put("uib/template/carousel/slide.html",
44521             "<div ng-class=\"{\n" +
44522             "    'active': active\n" +
44523             "  }\" class=\"item text-center\" ng-transclude></div>\n" +
44524             "");
44525         }]);
44526
44527         angular.module("uib/template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
44528           $templateCache.put("uib/template/datepicker/datepicker.html",
44529             "<div class=\"uib-datepicker\" ng-switch=\"datepickerMode\" role=\"application\" ng-keydown=\"keydown($event)\">\n" +
44530             "  <uib-daypicker ng-switch-when=\"day\" tabindex=\"0\"></uib-daypicker>\n" +
44531             "  <uib-monthpicker ng-switch-when=\"month\" tabindex=\"0\"></uib-monthpicker>\n" +
44532             "  <uib-yearpicker ng-switch-when=\"year\" tabindex=\"0\"></uib-yearpicker>\n" +
44533             "</div>\n" +
44534             "");
44535         }]);
44536
44537         angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", function($templateCache) {
44538           $templateCache.put("uib/template/datepicker/day.html",
44539             "<table class=\"uib-daypicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
44540             "  <thead>\n" +
44541             "    <tr>\n" +
44542             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
44543             "      <th colspan=\"{{::5 + showWeeks}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
44544             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
44545             "    </tr>\n" +
44546             "    <tr>\n" +
44547             "      <th ng-if=\"showWeeks\" class=\"text-center\"></th>\n" +
44548             "      <th ng-repeat=\"label in ::labels track by $index\" class=\"text-center\"><small aria-label=\"{{::label.full}}\">{{::label.abbr}}</small></th>\n" +
44549             "    </tr>\n" +
44550             "  </thead>\n" +
44551             "  <tbody>\n" +
44552             "    <tr class=\"uib-weeks\" ng-repeat=\"row in rows track by $index\">\n" +
44553             "      <td ng-if=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
44554             "      <td ng-repeat=\"dt in row\" class=\"uib-day text-center\" role=\"gridcell\"\n" +
44555             "        id=\"{{::dt.uid}}\"\n" +
44556             "        ng-class=\"::dt.customClass\">\n" +
44557             "        <button type=\"button\" class=\"btn btn-default btn-sm\"\n" +
44558             "          uib-is-class=\"\n" +
44559             "            'btn-info' for selectedDt,\n" +
44560             "            'active' for activeDt\n" +
44561             "            on dt\"\n" +
44562             "          ng-click=\"select(dt.date)\"\n" +
44563             "          ng-disabled=\"::dt.disabled\"\n" +
44564             "          tabindex=\"-1\"><span ng-class=\"::{'text-muted': dt.secondary, 'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
44565             "      </td>\n" +
44566             "    </tr>\n" +
44567             "  </tbody>\n" +
44568             "</table>\n" +
44569             "");
44570         }]);
44571
44572         angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", function($templateCache) {
44573           $templateCache.put("uib/template/datepicker/month.html",
44574             "<table class=\"uib-monthpicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
44575             "  <thead>\n" +
44576             "    <tr>\n" +
44577             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
44578             "      <th><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
44579             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
44580             "    </tr>\n" +
44581             "  </thead>\n" +
44582             "  <tbody>\n" +
44583             "    <tr class=\"uib-months\" ng-repeat=\"row in rows track by $index\">\n" +
44584             "      <td ng-repeat=\"dt in row\" class=\"uib-month text-center\" role=\"gridcell\"\n" +
44585             "        id=\"{{::dt.uid}}\"\n" +
44586             "        ng-class=\"::dt.customClass\">\n" +
44587             "        <button type=\"button\" class=\"btn btn-default\"\n" +
44588             "          uib-is-class=\"\n" +
44589             "            'btn-info' for selectedDt,\n" +
44590             "            'active' for activeDt\n" +
44591             "            on dt\"\n" +
44592             "          ng-click=\"select(dt.date)\"\n" +
44593             "          ng-disabled=\"::dt.disabled\"\n" +
44594             "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
44595             "      </td>\n" +
44596             "    </tr>\n" +
44597             "  </tbody>\n" +
44598             "</table>\n" +
44599             "");
44600         }]);
44601
44602         angular.module("uib/template/datepicker/year.html", []).run(["$templateCache", function($templateCache) {
44603           $templateCache.put("uib/template/datepicker/year.html",
44604             "<table class=\"uib-yearpicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
44605             "  <thead>\n" +
44606             "    <tr>\n" +
44607             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
44608             "      <th colspan=\"{{::columns - 2}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
44609             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
44610             "    </tr>\n" +
44611             "  </thead>\n" +
44612             "  <tbody>\n" +
44613             "    <tr class=\"uib-years\" ng-repeat=\"row in rows track by $index\">\n" +
44614             "      <td ng-repeat=\"dt in row\" class=\"uib-year text-center\" role=\"gridcell\"\n" +
44615             "        id=\"{{::dt.uid}}\"\n" +
44616             "        ng-class=\"::dt.customClass\">\n" +
44617             "        <button type=\"button\" class=\"btn btn-default\"\n" +
44618             "          uib-is-class=\"\n" +
44619             "            'btn-info' for selectedDt,\n" +
44620             "            'active' for activeDt\n" +
44621             "            on dt\"\n" +
44622             "          ng-click=\"select(dt.date)\"\n" +
44623             "          ng-disabled=\"::dt.disabled\"\n" +
44624             "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
44625             "      </td>\n" +
44626             "    </tr>\n" +
44627             "  </tbody>\n" +
44628             "</table>\n" +
44629             "");
44630         }]);
44631
44632         angular.module("uib/template/datepickerPopup/popup.html", []).run(["$templateCache", function($templateCache) {
44633           $templateCache.put("uib/template/datepickerPopup/popup.html",
44634             "<div>\n" +
44635             "  <ul class=\"uib-datepicker-popup dropdown-menu uib-position-measure\" dropdown-nested ng-if=\"isOpen\" ng-keydown=\"keydown($event)\" ng-click=\"$event.stopPropagation()\">\n" +
44636             "    <li ng-transclude></li>\n" +
44637             "    <li ng-if=\"showButtonBar\" class=\"uib-button-bar\">\n" +
44638             "      <span class=\"btn-group pull-left\">\n" +
44639             "        <button type=\"button\" class=\"btn btn-sm btn-info uib-datepicker-current\" ng-click=\"select('today', $event)\" ng-disabled=\"isDisabled('today')\">{{ getText('current') }}</button>\n" +
44640             "        <button type=\"button\" class=\"btn btn-sm btn-danger uib-clear\" ng-click=\"select(null, $event)\">{{ getText('clear') }}</button>\n" +
44641             "      </span>\n" +
44642             "      <button type=\"button\" class=\"btn btn-sm btn-success pull-right uib-close\" ng-click=\"close($event)\">{{ getText('close') }}</button>\n" +
44643             "    </li>\n" +
44644             "  </ul>\n" +
44645             "</div>\n" +
44646             "");
44647         }]);
44648
44649         angular.module("uib/template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
44650           $templateCache.put("uib/template/modal/backdrop.html",
44651             "<div class=\"modal-backdrop\"\n" +
44652             "     uib-modal-animation-class=\"fade\"\n" +
44653             "     modal-in-class=\"in\"\n" +
44654             "     ng-style=\"{'z-index': 1040 + (index && 1 || 0) + index*10}\"\n" +
44655             "></div>\n" +
44656             "");
44657         }]);
44658
44659         angular.module("uib/template/modal/window.html", []).run(["$templateCache", function($templateCache) {
44660           $templateCache.put("uib/template/modal/window.html",
44661             "<div modal-render=\"{{$isRendered}}\" tabindex=\"-1\" role=\"dialog\" class=\"modal\"\n" +
44662             "    uib-modal-animation-class=\"fade\"\n" +
44663             "    modal-in-class=\"in\"\n" +
44664             "    ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\">\n" +
44665             "    <div class=\"modal-dialog {{size ? 'modal-' + size : ''}}\"><div class=\"modal-content\" uib-modal-transclude></div></div>\n" +
44666             "</div>\n" +
44667             "");
44668         }]);
44669
44670         angular.module("uib/template/pager/pager.html", []).run(["$templateCache", function($templateCache) {
44671           $templateCache.put("uib/template/pager/pager.html",
44672             "<ul class=\"pager\">\n" +
44673             "  <li ng-class=\"{disabled: noPrevious()||ngDisabled, previous: align}\"><a href ng-click=\"selectPage(page - 1, $event)\">{{::getText('previous')}}</a></li>\n" +
44674             "  <li ng-class=\"{disabled: noNext()||ngDisabled, next: align}\"><a href ng-click=\"selectPage(page + 1, $event)\">{{::getText('next')}}</a></li>\n" +
44675             "</ul>\n" +
44676             "");
44677         }]);
44678
44679         angular.module("uib/template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
44680           $templateCache.put("uib/template/pagination/pagination.html",
44681             "<ul class=\"pagination\">\n" +
44682             "  <li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-first\"><a href ng-click=\"selectPage(1, $event)\">{{::getText('first')}}</a></li>\n" +
44683             "  <li ng-if=\"::directionLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-prev\"><a href ng-click=\"selectPage(page - 1, $event)\">{{::getText('previous')}}</a></li>\n" +
44684             "  <li ng-repeat=\"page in pages track by $index\" ng-class=\"{active: page.active,disabled: ngDisabled&&!page.active}\" class=\"pagination-page\"><a href ng-click=\"selectPage(page.number, $event)\">{{page.text}}</a></li>\n" +
44685             "  <li ng-if=\"::directionLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-next\"><a href ng-click=\"selectPage(page + 1, $event)\">{{::getText('next')}}</a></li>\n" +
44686             "  <li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-last\"><a href ng-click=\"selectPage(totalPages, $event)\">{{::getText('last')}}</a></li>\n" +
44687             "</ul>\n" +
44688             "");
44689         }]);
44690
44691         angular.module("uib/template/tooltip/tooltip-html-popup.html", []).run(["$templateCache", function($templateCache) {
44692           $templateCache.put("uib/template/tooltip/tooltip-html-popup.html",
44693             "<div class=\"tooltip\"\n" +
44694             "  tooltip-animation-class=\"fade\"\n" +
44695             "  uib-tooltip-classes\n" +
44696             "  ng-class=\"{ in: isOpen() }\">\n" +
44697             "  <div class=\"tooltip-arrow\"></div>\n" +
44698             "  <div class=\"tooltip-inner\" ng-bind-html=\"contentExp()\"></div>\n" +
44699             "</div>\n" +
44700             "");
44701         }]);
44702
44703         angular.module("uib/template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
44704           $templateCache.put("uib/template/tooltip/tooltip-popup.html",
44705             "<div class=\"tooltip\"\n" +
44706             "  tooltip-animation-class=\"fade\"\n" +
44707             "  uib-tooltip-classes\n" +
44708             "  ng-class=\"{ in: isOpen() }\">\n" +
44709             "  <div class=\"tooltip-arrow\"></div>\n" +
44710             "  <div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
44711             "</div>\n" +
44712             "");
44713         }]);
44714
44715         angular.module("uib/template/tooltip/tooltip-template-popup.html", []).run(["$templateCache", function($templateCache) {
44716           $templateCache.put("uib/template/tooltip/tooltip-template-popup.html",
44717             "<div class=\"tooltip\"\n" +
44718             "  tooltip-animation-class=\"fade\"\n" +
44719             "  uib-tooltip-classes\n" +
44720             "  ng-class=\"{ in: isOpen() }\">\n" +
44721             "  <div class=\"tooltip-arrow\"></div>\n" +
44722             "  <div class=\"tooltip-inner\"\n" +
44723             "    uib-tooltip-template-transclude=\"contentExp()\"\n" +
44724             "    tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
44725             "</div>\n" +
44726             "");
44727         }]);
44728
44729         angular.module("uib/template/popover/popover-html.html", []).run(["$templateCache", function($templateCache) {
44730           $templateCache.put("uib/template/popover/popover-html.html",
44731             "<div class=\"popover\"\n" +
44732             "  tooltip-animation-class=\"fade\"\n" +
44733             "  uib-tooltip-classes\n" +
44734             "  ng-class=\"{ in: isOpen() }\">\n" +
44735             "  <div class=\"arrow\"></div>\n" +
44736             "\n" +
44737             "  <div class=\"popover-inner\">\n" +
44738             "      <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
44739             "      <div class=\"popover-content\" ng-bind-html=\"contentExp()\"></div>\n" +
44740             "  </div>\n" +
44741             "</div>\n" +
44742             "");
44743         }]);
44744
44745         angular.module("uib/template/popover/popover-template.html", []).run(["$templateCache", function($templateCache) {
44746           $templateCache.put("uib/template/popover/popover-template.html",
44747             "<div class=\"popover\"\n" +
44748             "  tooltip-animation-class=\"fade\"\n" +
44749             "  uib-tooltip-classes\n" +
44750             "  ng-class=\"{ in: isOpen() }\">\n" +
44751             "  <div class=\"arrow\"></div>\n" +
44752             "\n" +
44753             "  <div class=\"popover-inner\">\n" +
44754             "      <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
44755             "      <div class=\"popover-content\"\n" +
44756             "        uib-tooltip-template-transclude=\"contentExp()\"\n" +
44757             "        tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
44758             "  </div>\n" +
44759             "</div>\n" +
44760             "");
44761         }]);
44762
44763         angular.module("uib/template/popover/popover.html", []).run(["$templateCache", function($templateCache) {
44764           $templateCache.put("uib/template/popover/popover.html",
44765             "<div class=\"popover\"\n" +
44766             "  tooltip-animation-class=\"fade\"\n" +
44767             "  uib-tooltip-classes\n" +
44768             "  ng-class=\"{ in: isOpen() }\">\n" +
44769             "  <div class=\"arrow\"></div>\n" +
44770             "\n" +
44771             "  <div class=\"popover-inner\">\n" +
44772             "      <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
44773             "      <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
44774             "  </div>\n" +
44775             "</div>\n" +
44776             "");
44777         }]);
44778
44779         angular.module("uib/template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
44780           $templateCache.put("uib/template/progressbar/bar.html",
44781             "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
44782             "");
44783         }]);
44784
44785         angular.module("uib/template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
44786           $templateCache.put("uib/template/progressbar/progress.html",
44787             "<div class=\"progress\" ng-transclude aria-labelledby=\"{{::title}}\"></div>");
44788         }]);
44789
44790         angular.module("uib/template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
44791           $templateCache.put("uib/template/progressbar/progressbar.html",
44792             "<div class=\"progress\">\n" +
44793             "  <div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
44794             "</div>\n" +
44795             "");
44796         }]);
44797
44798         angular.module("uib/template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
44799           $templateCache.put("uib/template/rating/rating.html",
44800             "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\" aria-valuetext=\"{{title}}\">\n" +
44801             "    <span ng-repeat-start=\"r in range track by $index\" class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
44802             "    <i ng-repeat-end ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\" ng-attr-title=\"{{r.title}}\"></i>\n" +
44803             "</span>\n" +
44804             "");
44805         }]);
44806
44807         angular.module("uib/template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
44808           $templateCache.put("uib/template/tabs/tab.html",
44809             "<li ng-class=\"[{active: active, disabled: disabled}, classes]\" class=\"uib-tab nav-item\">\n" +
44810             "  <a href ng-click=\"select($event)\" class=\"nav-link\" uib-tab-heading-transclude>{{heading}}</a>\n" +
44811             "</li>\n" +
44812             "");
44813         }]);
44814
44815         angular.module("uib/template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
44816           $templateCache.put("uib/template/tabs/tabset.html",
44817             "<div>\n" +
44818             "  <ul class=\"nav nav-{{tabset.type || 'tabs'}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
44819             "  <div class=\"tab-content\">\n" +
44820             "    <div class=\"tab-pane\"\n" +
44821             "         ng-repeat=\"tab in tabset.tabs\"\n" +
44822             "         ng-class=\"{active: tabset.active === tab.index}\"\n" +
44823             "         uib-tab-content-transclude=\"tab\">\n" +
44824             "    </div>\n" +
44825             "  </div>\n" +
44826             "</div>\n" +
44827             "");
44828         }]);
44829
44830         angular.module("uib/template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) {
44831           $templateCache.put("uib/template/timepicker/timepicker.html",
44832             "<table class=\"uib-timepicker\">\n" +
44833             "  <tbody>\n" +
44834             "    <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
44835             "      <td class=\"uib-increment hours\"><a ng-click=\"incrementHours()\" ng-class=\"{disabled: noIncrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementHours()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
44836             "      <td>&nbsp;</td>\n" +
44837             "      <td class=\"uib-increment minutes\"><a ng-click=\"incrementMinutes()\" ng-class=\"{disabled: noIncrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementMinutes()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
44838             "      <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
44839             "      <td ng-show=\"showSeconds\" class=\"uib-increment seconds\"><a ng-click=\"incrementSeconds()\" ng-class=\"{disabled: noIncrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementSeconds()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
44840             "      <td ng-show=\"showMeridian\"></td>\n" +
44841             "    </tr>\n" +
44842             "    <tr>\n" +
44843             "      <td class=\"form-group uib-time hours\" ng-class=\"{'has-error': invalidHours}\">\n" +
44844             "        <input type=\"text\" placeholder=\"HH\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementHours()\" ng-blur=\"blur()\">\n" +
44845             "      </td>\n" +
44846             "      <td class=\"uib-separator\">:</td>\n" +
44847             "      <td class=\"form-group uib-time minutes\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
44848             "        <input type=\"text\" placeholder=\"MM\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementMinutes()\" ng-blur=\"blur()\">\n" +
44849             "      </td>\n" +
44850             "      <td ng-show=\"showSeconds\" class=\"uib-separator\">:</td>\n" +
44851             "      <td class=\"form-group uib-time seconds\" ng-class=\"{'has-error': invalidSeconds}\" ng-show=\"showSeconds\">\n" +
44852             "        <input type=\"text\" placeholder=\"SS\" ng-model=\"seconds\" ng-change=\"updateSeconds()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementSeconds()\" ng-blur=\"blur()\">\n" +
44853             "      </td>\n" +
44854             "      <td ng-show=\"showMeridian\" class=\"uib-time am-pm\"><button type=\"button\" ng-class=\"{disabled: noToggleMeridian()}\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\" ng-disabled=\"noToggleMeridian()\" tabindex=\"{{::tabindex}}\">{{meridian}}</button></td>\n" +
44855             "    </tr>\n" +
44856             "    <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
44857             "      <td class=\"uib-decrement hours\"><a ng-click=\"decrementHours()\" ng-class=\"{disabled: noDecrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementHours()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
44858             "      <td>&nbsp;</td>\n" +
44859             "      <td class=\"uib-decrement minutes\"><a ng-click=\"decrementMinutes()\" ng-class=\"{disabled: noDecrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementMinutes()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
44860             "      <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
44861             "      <td ng-show=\"showSeconds\" class=\"uib-decrement seconds\"><a ng-click=\"decrementSeconds()\" ng-class=\"{disabled: noDecrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementSeconds()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
44862             "      <td ng-show=\"showMeridian\"></td>\n" +
44863             "    </tr>\n" +
44864             "  </tbody>\n" +
44865             "</table>\n" +
44866             "");
44867         }]);
44868
44869         angular.module("uib/template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) {
44870           $templateCache.put("uib/template/typeahead/typeahead-match.html",
44871             "<a href\n" +
44872             "   tabindex=\"-1\"\n" +
44873             "   ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"\n" +
44874             "   ng-attr-title=\"{{match.label}}\"></a>\n" +
44875             "");
44876         }]);
44877
44878         angular.module("uib/template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
44879           $templateCache.put("uib/template/typeahead/typeahead-popup.html",
44880             "<ul class=\"dropdown-menu\" ng-show=\"isOpen() && !moveInProgress\" ng-style=\"{top: position().top+'px', left: position().left+'px'}\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
44881             "    <li ng-repeat=\"match in matches track by $index\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index, $event)\" role=\"option\" id=\"{{::match.id}}\">\n" +
44882             "        <div uib-typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
44883             "    </li>\n" +
44884             "</ul>\n" +
44885             "");
44886         }]);
44887         angular.module('ui.bootstrap.carousel').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibCarouselCss && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'); angular.$$uibCarouselCss = true; });
44888         angular.module('ui.bootstrap.datepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'); angular.$$uibDatepickerCss = true; });
44889         angular.module('ui.bootstrap.position').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibPositionCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'); angular.$$uibPositionCss = true; });
44890         angular.module('ui.bootstrap.datepickerPopup').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerpopupCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'); angular.$$uibDatepickerpopupCss = true; });
44891         angular.module('ui.bootstrap.tooltip').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });
44892         angular.module('ui.bootstrap.timepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTimepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-time input{width:50px;}</style>'); angular.$$uibTimepickerCss = true; });
44893         angular.module('ui.bootstrap.typeahead').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; });
44894
44895 /***/ },
44896 /* 8 */
44897 /***/ function(module, exports) {
44898
44899         var app;
44900         (function (app) {
44901             var declares;
44902             (function (declares) {
44903                 var CommandInfo = (function () {
44904                     function CommandInfo(name) {
44905                         this.name = name;
44906                     }
44907                     return CommandInfo;
44908                 })();
44909                 declares.CommandInfo = CommandInfo;
44910             })(declares = app.declares || (app.declares = {}));
44911         })(app || (app = {}));
44912         var app;
44913         (function (app) {
44914             var services;
44915             (function (services) {
44916                 var APIEndPoint = (function () {
44917                     function APIEndPoint($resource, $http) {
44918                         this.$resource = $resource;
44919                         this.$http = $http;
44920                     }
44921                     APIEndPoint.prototype.resource = function (endPoint, data) {
44922                         var customAction = {
44923                             method: 'GET',
44924                             isArray: false
44925                         };
44926                         var execute = {
44927                             method: 'POST',
44928                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
44929                         };
44930                         return this.$resource(endPoint, {}, { execute: execute });
44931                     };
44932                     APIEndPoint.prototype.getOptionControlFile = function (command) {
44933                         var endPoint = '/api/v1/optionControlFile/' + command;
44934                         return this.resource(endPoint, {}).get();
44935                     };
44936                     APIEndPoint.prototype.getFiles = function (fileId) {
44937                         var endPoint = '/api/v1/workspace';
44938                         if (fileId) {
44939                             endPoint += '/' + fileId;
44940                         }
44941                         return this.resource(endPoint, {}).get();
44942                     };
44943                     APIEndPoint.prototype.getDirectories = function () {
44944                         var endPoint = '/api/v1/all/workspace/directory';
44945                         return this.resource(endPoint, {}).get();
44946                     };
44947                     APIEndPoint.prototype.getTags = function () {
44948                         var endPoint = '/api/v1/tagList';
44949                         return this.resource(endPoint, {}).get();
44950                     };
44951                     APIEndPoint.prototype.getCommands = function () {
44952                         var endPoint = '/api/v1/commandList';
44953                         return this.resource(endPoint, {}).get();
44954                     };
44955                     APIEndPoint.prototype.execute = function (data) {
44956                         var endPoint = '/api/v1/execution';
44957                         var fd = new FormData();
44958                         fd.append('data', data);
44959                         return this.$http.post(endPoint, fd, {
44960                             headers: { 'Content-Type': undefined },
44961                             transformRequest: angular.identity
44962                         });
44963                     };
44964                     APIEndPoint.prototype.debug = function () {
44965                         var endPoint = '/api/v1/debug';
44966                         return this.$http.get(endPoint);
44967                     };
44968                     APIEndPoint.prototype.upload = function () {
44969                         var endPoint = '/api/v1/upload';
44970                         return this.$http.get(endPoint);
44971                     };
44972                     APIEndPoint.prototype.help = function (command) {
44973                         var endPoint = '/api/v1/help/' + command;
44974                         return this.$http.get(endPoint);
44975                     };
44976                     return APIEndPoint;
44977                 })();
44978                 services.APIEndPoint = APIEndPoint;
44979             })(services = app.services || (app.services = {}));
44980         })(app || (app = {}));
44981         var app;
44982         (function (app) {
44983             var services;
44984             (function (services) {
44985                 var MyModal = (function () {
44986                     function MyModal($uibModal) {
44987                         this.$uibModal = $uibModal;
44988                         this.modalOption = {
44989                             backdrop: true,
44990                             controller: null,
44991                             templateUrl: null,
44992                             size: null
44993                         };
44994                     }
44995                     MyModal.prototype.open = function (modalName) {
44996                         if (modalName === 'SelectCommand') {
44997                             this.modalOption.templateUrl = 'templates/select-command.html';
44998                             this.modalOption.size = 'lg';
44999                         }
45000                         return this.$uibModal.open(this.modalOption);
45001                     };
45002                     MyModal.prototype.selectCommand = function () {
45003                         this.modalOption.templateUrl = 'templates/select-command.html';
45004                         this.modalOption.controller = 'selectCommandController';
45005                         this.modalOption.controllerAs = 'c';
45006                         this.modalOption.size = 'lg';
45007                         return this.$uibModal.open(this.modalOption);
45008                     };
45009                     MyModal.prototype.preview = function () {
45010                         this.modalOption.templateUrl = 'templates/preview.html';
45011                         this.modalOption.controller = 'previewController';
45012                         this.modalOption.controllerAs = 'c';
45013                         this.modalOption.size = 'lg';
45014                         return this.$uibModal.open(this.modalOption);
45015                     };
45016                     MyModal.prototype.upload = function () {
45017                         this.modalOption.templateUrl = 'templates/upload.html';
45018                         this.modalOption.controller = 'uploadController';
45019                         this.modalOption.controllerAs = 'c';
45020                         this.modalOption.size = 'lg';
45021                         return this.$uibModal.open(this.modalOption);
45022                     };
45023                     MyModal.$inject = ['$uibModal'];
45024                     return MyModal;
45025                 })();
45026                 services.MyModal = MyModal;
45027             })(services = app.services || (app.services = {}));
45028         })(app || (app = {}));
45029         var app;
45030         (function (app) {
45031             var services;
45032             (function (services) {
45033                 var WebSocket = (function () {
45034                     function WebSocket($rootScope) {
45035                         this.$rootScope = $rootScope;
45036                         this.socket = io.connect();
45037                     }
45038                     WebSocket.prototype.on = function (eventName, callback) {
45039                         var socket = this.socket;
45040                         var rootScope = this.$rootScope;
45041                         socket.on(eventName, function () {
45042                             var args = arguments;
45043                             rootScope.$apply(function () {
45044                                 callback.apply(socket, args);
45045                             });
45046                         });
45047                     };
45048                     WebSocket.prototype.emit = function (eventName, data, callback) {
45049                         var socket = this.socket;
45050                         var rootScope = this.$rootScope;
45051                         this.socket.emit(eventName, data, function () {
45052                             var args = arguments;
45053                             rootScope.$apply(function () {
45054                                 if (callback)
45055                                     callback.apply(socket, args);
45056                             });
45057                         });
45058                     };
45059                     return WebSocket;
45060                 })();
45061                 services.WebSocket = WebSocket;
45062             })(services = app.services || (app.services = {}));
45063         })(app || (app = {}));
45064         var app;
45065         (function (app) {
45066             var services;
45067             (function (services) {
45068                 var Console = (function () {
45069                     function Console(WebSocket, $rootScope) {
45070                         this.WebSocket = WebSocket;
45071                         this.$rootScope = $rootScope;
45072                         this.WebSocket = WebSocket;
45073                         this.$rootScope = $rootScope;
45074                         this.directiveIDs = [];
45075                         var directiveIDs = this.directiveIDs;
45076                         this.WebSocket.on('console', function (d) {
45077                             var id = d.id;
45078                             var message = d.message;
45079                             if (directiveIDs.indexOf(id) > -1) {
45080                                 $rootScope.$emit(id, message);
45081                             }
45082                         });
45083                     }
45084                     Console.prototype.addDirective = function (id) {
45085                         if (!(this.directiveIDs.indexOf(id) > -1)) {
45086                             this.directiveIDs.push(id);
45087                         }
45088                     };
45089                     Console.prototype.removeDirective = function (id) {
45090                         var i = this.directiveIDs.indexOf(id);
45091                         if (i > -1) {
45092                             this.directiveIDs.splice(i, 1);
45093                         }
45094                     };
45095                     Console.prototype.showIDs = function () {
45096                         console.log(this.directiveIDs);
45097                     };
45098                     return Console;
45099                 })();
45100                 services.Console = Console;
45101             })(services = app.services || (app.services = {}));
45102         })(app || (app = {}));
45103         var app;
45104         (function (app) {
45105             var directives;
45106             (function (directives) {
45107                 var Command = (function () {
45108                     function Command() {
45109                         this.restrict = 'E';
45110                         this.replace = true;
45111                         this.scope = true;
45112                         this.controller = 'commandController';
45113                         this.controllerAs = 'ctrl';
45114                         this.bindToController = {
45115                             index: '=',
45116                             name: '=',
45117                             remove: '&',
45118                             list: '='
45119                         };
45120                         this.templateUrl = 'templates/command.html';
45121                     }
45122                     Command.Factory = function () {
45123                         var directive = function () {
45124                             return new Command();
45125                         };
45126                         directive.$inject = [];
45127                         return directive;
45128                     };
45129                     return Command;
45130                 })();
45131                 directives.Command = Command;
45132                 var CommandController = (function () {
45133                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
45134                         this.APIEndPoint = APIEndPoint;
45135                         this.$scope = $scope;
45136                         this.MyModal = MyModal;
45137                         this.WebSocket = WebSocket;
45138                         this.$window = $window;
45139                         this.$rootScope = $rootScope;
45140                         this.Console = Console;
45141                         var controller = this;
45142                         this.APIEndPoint
45143                             .getOptionControlFile(this.name)
45144                             .$promise
45145                             .then(function (result) {
45146                             controller.options = result.info;
45147                         });
45148                         this.APIEndPoint
45149                             .getDirectories()
45150                             .$promise
45151                             .then(function (result) {
45152                             controller.dirs = result.info;
45153                         });
45154                         this.heading = "[" + this.index + "]: dcdFilePrint";
45155                         this.isOpen = true;
45156                         this.$scope.$on('close', function () {
45157                             controller.isOpen = false;
45158                         });
45159                         function guid() {
45160                             function s4() {
45161                                 return Math.floor((1 + Math.random()) * 0x10000)
45162                                     .toString(16)
45163                                     .substring(1);
45164                             }
45165                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
45166                                 s4() + '-' + s4() + s4() + s4();
45167                         }
45168                         this.uuid = guid();
45169                         this.Console.addDirective(this.uuid);
45170                         this.Console.showIDs();
45171                     }
45172                     CommandController.prototype.submit = function () {
45173                         var opt = [];
45174                         angular.forEach(this.options, function (option) {
45175                             var obj = {
45176                                 name: option.option,
45177                                 arguments: []
45178                             };
45179                             angular.forEach(option.arg, function (arg) {
45180                                 if (arg.input) {
45181                                     if (typeof arg.input === 'object') {
45182                                         obj.arguments.push(arg.input.name);
45183                                     }
45184                                     else {
45185                                         obj.arguments.push(arg.input);
45186                                     }
45187                                 }
45188                             });
45189                             if (obj.arguments.length > 0) {
45190                                 opt.push(obj);
45191                             }
45192                         });
45193                         var execObj = {
45194                             command: this.name,
45195                             workspace: this.workspace.fileId,
45196                             options: opt
45197                         };
45198                         this.APIEndPoint
45199                             .execute(JSON.stringify(execObj))
45200                             .then(function (result) {
45201                             console.log(result);
45202                         });
45203                     };
45204                     CommandController.prototype.removeMySelf = function (index) {
45205                         this.$scope.$destroy();
45206                         this.Console.removeDirective(this.uuid);
45207                         this.remove()(index, this.list);
45208                         this.Console.showIDs();
45209                     };
45210                     CommandController.prototype.reloadFiles = function () {
45211                         var _this = this;
45212                         var fileId = this.workspace.fileId;
45213                         this.APIEndPoint
45214                             .getFiles(fileId)
45215                             .$promise
45216                             .then(function (result) {
45217                             var status = result.status;
45218                             if (status === 'success') {
45219                                 _this.files = result.info;
45220                             }
45221                             else {
45222                                 console.log(result.message);
45223                             }
45224                         });
45225                     };
45226                     CommandController.prototype.debug = function () {
45227                         var div = angular.element(this.$window.document).find("div");
45228                         var consoleTag;
45229                         var parametersTag;
45230                         angular.forEach(div, function (v) {
45231                             if (v.className === "panel-body console") {
45232                                 consoleTag = v;
45233                             }
45234                             else if (v.className === "row parameters-console") {
45235                                 parametersTag = v;
45236                             }
45237                         });
45238                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
45239                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
45240                         consoleTag.style.height = consoleHeight;
45241                         consoleTag.style.width = consoleWidth;
45242                     };
45243                     CommandController.prototype.help = function () {
45244                         this.APIEndPoint
45245                             .help(this.name)
45246                             .then(function (result) {
45247                             console.log(result);
45248                         });
45249                     };
45250                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
45251                     return CommandController;
45252                 })();
45253                 directives.CommandController = CommandController;
45254             })(directives = app.directives || (app.directives = {}));
45255         })(app || (app = {}));
45256         var app;
45257         (function (app) {
45258             var directives;
45259             (function (directives) {
45260                 var HeaderMenu = (function () {
45261                     function HeaderMenu() {
45262                         this.restrict = 'E';
45263                         this.replace = true;
45264                         this.templateUrl = 'templates/header-menu.html';
45265                         this.controller = 'HeaderMenuController';
45266                         this.controllerAs = 'hmc';
45267                         this.scope = true;
45268                     }
45269                     HeaderMenu.Factory = function () {
45270                         var directive = function () {
45271                             return new HeaderMenu();
45272                         };
45273                         return directive;
45274                     };
45275                     return HeaderMenu;
45276                 })();
45277                 directives.HeaderMenu = HeaderMenu;
45278                 var HeaderMenuController = (function () {
45279                     function HeaderMenuController($state) {
45280                         this.$state = $state;
45281                         this.isExecution = this.$state.current.name === 'execution';
45282                         this.isWorkspace = this.$state.current.name === 'workspace';
45283                         this.isHistory = this.$state.current.name === 'history';
45284                     }
45285                     HeaderMenuController.prototype.transit = function (state) {
45286                         this.$state.go(state);
45287                     };
45288                     HeaderMenuController.$inject = ['$state'];
45289                     return HeaderMenuController;
45290                 })();
45291                 directives.HeaderMenuController = HeaderMenuController;
45292             })(directives = app.directives || (app.directives = {}));
45293         })(app || (app = {}));
45294         var app;
45295         (function (app) {
45296             var directives;
45297             (function (directives) {
45298                 var Option = (function () {
45299                     function Option() {
45300                         this.restrict = 'E';
45301                         this.replace = true;
45302                         this.controller = 'optionController';
45303                         this.bindToController = {
45304                             info: '=',
45305                             files: '='
45306                         };
45307                         this.scope = true;
45308                         this.templateUrl = 'templates/option.html';
45309                         this.controllerAs = 'ctrl';
45310                     }
45311                     Option.Factory = function () {
45312                         var directive = function () {
45313                             return new Option();
45314                         };
45315                         directive.$inject = [];
45316                         return directive;
45317                     };
45318                     return Option;
45319                 })();
45320                 directives.Option = Option;
45321                 var OptionController = (function () {
45322                     function OptionController() {
45323                         var controller = this;
45324                         angular.forEach(controller.info.arg, function (arg) {
45325                             if (arg.initialValue) {
45326                                 if (arg.formType === 'number') {
45327                                     arg.input = parseInt(arg.initialValue);
45328                                 }
45329                                 else {
45330                                     arg.input = arg.initialValue;
45331                                 }
45332                             }
45333                         });
45334                     }
45335                     OptionController.$inject = [];
45336                     return OptionController;
45337                 })();
45338                 directives.OptionController = OptionController;
45339             })(directives = app.directives || (app.directives = {}));
45340         })(app || (app = {}));
45341         var app;
45342         (function (app) {
45343             var directives;
45344             (function (directives) {
45345                 var Directory = (function () {
45346                     function Directory() {
45347                         this.restrict = 'E';
45348                         this.replace = true;
45349                         this.controller = 'directoryController';
45350                         this.controllerAs = 'ctrl';
45351                         this.bindToController = {
45352                             info: '=',
45353                             add: '&',
45354                             list: '=',
45355                             files: '='
45356                         };
45357                         this.templateUrl = 'templates/directory.html';
45358                     }
45359                     Directory.Factory = function () {
45360                         var directive = function () {
45361                             return new Directory();
45362                         };
45363                         return directive;
45364                     };
45365                     return Directory;
45366                 })();
45367                 directives.Directory = Directory;
45368                 var DirectoryController = (function () {
45369                     function DirectoryController(APIEndPoint, $scope) {
45370                         this.APIEndPoint = APIEndPoint;
45371                         this.$scope = $scope;
45372                         var controller = this;
45373                         this.APIEndPoint
45374                             .getFiles(this.info.fileId)
45375                             .$promise
45376                             .then(function (result) {
45377                             if (result.status === 'success') {
45378                                 controller.files = result.info;
45379                                 angular.forEach(result.info, function (file) {
45380                                     if (file.fileType === '0') {
45381                                         var o = file;
45382                                         if (controller.info.path === '/') {
45383                                             o.path = '/' + file.name;
45384                                         }
45385                                         else {
45386                                             o.path = controller.info.path + '/' + file.name;
45387                                         }
45388                                         controller.add()(o, controller.list);
45389                                     }
45390                                 });
45391                             }
45392                             ;
45393                         });
45394                     }
45395                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
45396                     return DirectoryController;
45397                 })();
45398                 directives.DirectoryController = DirectoryController;
45399             })(directives = app.directives || (app.directives = {}));
45400         })(app || (app = {}));
45401         var app;
45402         (function (app) {
45403             var directives;
45404             (function (directives) {
45405                 var Upload = (function () {
45406                     function Upload() {
45407                         this.restrict = 'E';
45408                         this.replace = true;
45409                         this.scope = true;
45410                         this.controller = 'UploadController';
45411                         this.controllerAs = 'ctrl';
45412                         this.bindToController = {
45413                             index: '=',
45414                             name: '=',
45415                             remove: '&',
45416                             list: '='
45417                         };
45418                         this.templateUrl = 'templates/upload.html';
45419                         console.log("templates/upload.html-constructor");
45420                     }
45421                     Upload.Factory = function () {
45422                         var directive = function () {
45423                             return new Upload();
45424                         };
45425                         directive.$inject = [];
45426                         return directive;
45427                     };
45428                     return Upload;
45429                 })();
45430                 directives.Upload = Upload;
45431                 var UploadController = (function () {
45432                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
45433                         this.APIEndPoint = APIEndPoint;
45434                         this.$scope = $scope;
45435                         this.MyModal = MyModal;
45436                         this.WebSocket = WebSocket;
45437                         this.$window = $window;
45438                         this.$rootScope = $rootScope;
45439                         this.Console = Console;
45440                         var controller = this;
45441                         console.log("directive.upload-constructor");
45442                     }
45443                     UploadController.prototype.submit = function () {
45444                         console.log("submit: function not supported¥n");
45445                     };
45446                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
45447                     return UploadController;
45448                 })();
45449                 directives.UploadController = UploadController;
45450             })(directives = app.directives || (app.directives = {}));
45451         })(app || (app = {}));
45452         var app;
45453         (function (app) {
45454             var controllers;
45455             (function (controllers) {
45456                 var Execution = (function () {
45457                     function Execution(MyModal, $scope) {
45458                         this.MyModal = MyModal;
45459                         this.$scope = $scope;
45460                         this.commandInfoList = [];
45461                     }
45462                     ;
45463                     Execution.prototype.add = function () {
45464                         this.$scope.$broadcast('close');
45465                         var commandInfoList = this.commandInfoList;
45466                         var commandInstance = this.MyModal.selectCommand();
45467                         commandInstance
45468                             .result
45469                             .then(function (command) {
45470                             commandInfoList.push(new app.declares.CommandInfo(command));
45471                         });
45472                     };
45473                     Execution.prototype.open = function () {
45474                         var result = this.MyModal.open('SelectCommand');
45475                         console.log(result);
45476                     };
45477                     Execution.prototype.remove = function (index, list) {
45478                         list.splice(index, 1);
45479                     };
45480                     Execution.prototype.close = function () {
45481                         console.log("close");
45482                     };
45483                     Execution.$inject = ['MyModal', '$scope'];
45484                     return Execution;
45485                 })();
45486                 controllers.Execution = Execution;
45487             })(controllers = app.controllers || (app.controllers = {}));
45488         })(app || (app = {}));
45489         var app;
45490         (function (app) {
45491             var controllers;
45492             (function (controllers) {
45493                 var Workspace = (function () {
45494                     function Workspace($scope, APIEndPoint, MyModal) {
45495                         this.$scope = $scope;
45496                         this.APIEndPoint = APIEndPoint;
45497                         this.MyModal = MyModal;
45498                         this.directoryList = [];
45499                         var controller = this;
45500                         var directoryList = this.directoryList;
45501                         var o = {
45502                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
45503                             name: '',
45504                             parentId: '',
45505                             fileType: '',
45506                             createdAt: '',
45507                             updatedAt: '',
45508                             path: '/'
45509                         };
45510                         directoryList.push(o);
45511                     }
45512                     Workspace.prototype.addDirectory = function (info, directoryList) {
45513                         directoryList.push(info);
45514                     };
45515                     Workspace.prototype.upload = function () {
45516                         this.MyModal.upload();
45517                     };
45518                     Workspace.prototype.debug = function () {
45519                         this.MyModal.preview();
45520                     };
45521                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
45522                     return Workspace;
45523                 })();
45524                 controllers.Workspace = Workspace;
45525             })(controllers = app.controllers || (app.controllers = {}));
45526         })(app || (app = {}));
45527         var app;
45528         (function (app) {
45529             var controllers;
45530             (function (controllers) {
45531                 var History = (function () {
45532                     function History($scope) {
45533                         this.page = "History";
45534                     }
45535                     History.$inject = ['$scope'];
45536                     return History;
45537                 })();
45538                 controllers.History = History;
45539             })(controllers = app.controllers || (app.controllers = {}));
45540         })(app || (app = {}));
45541         var app;
45542         (function (app) {
45543             var controllers;
45544             (function (controllers) {
45545                 var SelectCommand = (function () {
45546                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
45547                         this.APIEndPoint = APIEndPoint;
45548                         this.$modalInstance = $modalInstance;
45549                         var controller = this;
45550                         this.APIEndPoint
45551                             .getTags()
45552                             .$promise.then(function (result) {
45553                             controller.tags = result.info;
45554                         });
45555                         this.APIEndPoint
45556                             .getCommands()
45557                             .$promise.then(function (result) {
45558                             controller.commands = result.info;
45559                         });
45560                         this.currentTag = 'all';
45561                     }
45562                     SelectCommand.prototype.changeTag = function (tag) {
45563                         this.currentTag = tag;
45564                     };
45565                     SelectCommand.prototype.selectCommand = function (command) {
45566                         this.$modalInstance.close(command);
45567                     };
45568                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
45569                     return SelectCommand;
45570                 })();
45571                 controllers.SelectCommand = SelectCommand;
45572             })(controllers = app.controllers || (app.controllers = {}));
45573         })(app || (app = {}));
45574         var app;
45575         (function (app) {
45576             var controllers;
45577             (function (controllers) {
45578                 var Upload = (function () {
45579                     function Upload($scope, APIEndPoint, $modalInstance) {
45580                         this.APIEndPoint = APIEndPoint;
45581                         this.$modalInstance = $modalInstance;
45582                         var controller = this;
45583                         console.log('controller.upload-controllers');
45584                     }
45585                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
45586                     return Upload;
45587                 })();
45588                 controllers.Upload = Upload;
45589             })(controllers = app.controllers || (app.controllers = {}));
45590         })(app || (app = {}));
45591         var app;
45592         (function (app) {
45593             var controllers;
45594             (function (controllers) {
45595                 var Preview = (function () {
45596                     function Preview($scope, APIEndPoint, $modalInstance) {
45597                         this.APIEndPoint = APIEndPoint;
45598                         this.$modalInstance = $modalInstance;
45599                         var controller = this;
45600                         console.log('preview');
45601                     }
45602                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
45603                     return Preview;
45604                 })();
45605                 controllers.Preview = Preview;
45606             })(controllers = app.controllers || (app.controllers = {}));
45607         })(app || (app = {}));
45608         var filters;
45609         (function (filters) {
45610             function Tag() {
45611                 return function (commands, tag) {
45612                     var result = [];
45613                     angular.forEach(commands, function (command) {
45614                         var flag = false;
45615                         angular.forEach(command.tags, function (value) {
45616                             if (tag === value)
45617                                 flag = true;
45618                         });
45619                         if (flag)
45620                             result.push(command);
45621                     });
45622                     return result;
45623                 };
45624             }
45625             filters.Tag = Tag;
45626         })(filters || (filters = {}));
45627         var app;
45628         (function (app) {
45629             'use strict';
45630             var appName = 'zephyr';
45631             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
45632             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
45633                 $urlRouterProvider.otherwise('/execution');
45634                 $locationProvider.html5Mode({
45635                     enabled: true,
45636                     requireBase: false
45637                 });
45638                 $stateProvider
45639                     .state('execution', {
45640                     url: '/execution',
45641                     templateUrl: 'templates/execution.html',
45642                     controller: 'executionController',
45643                     controllerAs: 'c'
45644                 })
45645                     .state('workspace', {
45646                     url: '/workspace',
45647                     templateUrl: 'templates/workspace.html',
45648                     controller: 'workspaceController',
45649                     controllerAs: 'c'
45650                 })
45651                     .state('history', {
45652                     url: '/history',
45653                     templateUrl: 'templates/history.html',
45654                     controller: 'historyController',
45655                     controllerAs: 'c'
45656                 });
45657             });
45658             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
45659             app.zephyr.service('MyModal', app.services.MyModal);
45660             app.zephyr.service('WebSocket', app.services.WebSocket);
45661             app.zephyr.service('Console', app.services.Console);
45662             app.zephyr.filter('Tag', filters.Tag);
45663             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
45664             app.zephyr.controller('previewController', app.controllers.Preview);
45665             app.zephyr.controller('uploadController', app.controllers.Upload);
45666             app.zephyr.controller('executionController', app.controllers.Execution);
45667             app.zephyr.controller('workspaceController', app.controllers.Workspace);
45668             app.zephyr.controller('historyController', app.controllers.History);
45669             app.zephyr.controller('commandController', app.directives.CommandController);
45670             app.zephyr.controller('optionController', app.directives.OptionController);
45671             app.zephyr.controller('directoryController', app.directives.DirectoryController);
45672             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
45673             app.zephyr.controller('uploadController', app.directives.UploadController);
45674             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
45675             app.zephyr.directive('command', app.directives.Command.Factory());
45676             app.zephyr.directive('option', app.directives.Option.Factory());
45677             app.zephyr.directive('directory', app.directives.Directory.Factory());
45678         })(app || (app = {}));
45679
45680
45681 /***/ },
45682 /* 9 */
45683 /***/ function(module, exports) {
45684
45685         var app;
45686         (function (app) {
45687             var declares;
45688             (function (declares) {
45689                 var CommandInfo = (function () {
45690                     function CommandInfo(name) {
45691                         this.name = name;
45692                     }
45693                     return CommandInfo;
45694                 })();
45695                 declares.CommandInfo = CommandInfo;
45696             })(declares = app.declares || (app.declares = {}));
45697         })(app || (app = {}));
45698         var app;
45699         (function (app) {
45700             var services;
45701             (function (services) {
45702                 var APIEndPoint = (function () {
45703                     function APIEndPoint($resource, $http) {
45704                         this.$resource = $resource;
45705                         this.$http = $http;
45706                     }
45707                     APIEndPoint.prototype.resource = function (endPoint, data) {
45708                         var customAction = {
45709                             method: 'GET',
45710                             isArray: false
45711                         };
45712                         var execute = {
45713                             method: 'POST',
45714                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
45715                         };
45716                         return this.$resource(endPoint, {}, { execute: execute });
45717                     };
45718                     APIEndPoint.prototype.getOptionControlFile = function (command) {
45719                         var endPoint = '/api/v1/optionControlFile/' + command;
45720                         return this.resource(endPoint, {}).get();
45721                     };
45722                     APIEndPoint.prototype.getFiles = function (fileId) {
45723                         var endPoint = '/api/v1/workspace';
45724                         if (fileId) {
45725                             endPoint += '/' + fileId;
45726                         }
45727                         return this.resource(endPoint, {}).get();
45728                     };
45729                     APIEndPoint.prototype.getDirectories = function () {
45730                         var endPoint = '/api/v1/all/workspace/directory';
45731                         return this.resource(endPoint, {}).get();
45732                     };
45733                     APIEndPoint.prototype.getTags = function () {
45734                         var endPoint = '/api/v1/tagList';
45735                         return this.resource(endPoint, {}).get();
45736                     };
45737                     APIEndPoint.prototype.getCommands = function () {
45738                         var endPoint = '/api/v1/commandList';
45739                         return this.resource(endPoint, {}).get();
45740                     };
45741                     APIEndPoint.prototype.execute = function (data) {
45742                         var endPoint = '/api/v1/execution';
45743                         var fd = new FormData();
45744                         fd.append('data', data);
45745                         return this.$http.post(endPoint, fd, {
45746                             headers: { 'Content-Type': undefined },
45747                             transformRequest: angular.identity
45748                         });
45749                     };
45750                     APIEndPoint.prototype.debug = function () {
45751                         var endPoint = '/api/v1/debug';
45752                         return this.$http.get(endPoint);
45753                     };
45754                     APIEndPoint.prototype.upload = function () {
45755                         var endPoint = '/api/v1/upload';
45756                         return this.$http.get(endPoint);
45757                     };
45758                     APIEndPoint.prototype.help = function (command) {
45759                         var endPoint = '/api/v1/help/' + command;
45760                         return this.$http.get(endPoint);
45761                     };
45762                     return APIEndPoint;
45763                 })();
45764                 services.APIEndPoint = APIEndPoint;
45765             })(services = app.services || (app.services = {}));
45766         })(app || (app = {}));
45767         var app;
45768         (function (app) {
45769             var services;
45770             (function (services) {
45771                 var MyModal = (function () {
45772                     function MyModal($uibModal) {
45773                         this.$uibModal = $uibModal;
45774                         this.modalOption = {
45775                             backdrop: true,
45776                             controller: null,
45777                             templateUrl: null,
45778                             size: null
45779                         };
45780                     }
45781                     MyModal.prototype.open = function (modalName) {
45782                         if (modalName === 'SelectCommand') {
45783                             this.modalOption.templateUrl = 'templates/select-command.html';
45784                             this.modalOption.size = 'lg';
45785                         }
45786                         return this.$uibModal.open(this.modalOption);
45787                     };
45788                     MyModal.prototype.selectCommand = function () {
45789                         this.modalOption.templateUrl = 'templates/select-command.html';
45790                         this.modalOption.controller = 'selectCommandController';
45791                         this.modalOption.controllerAs = 'c';
45792                         this.modalOption.size = 'lg';
45793                         return this.$uibModal.open(this.modalOption);
45794                     };
45795                     MyModal.prototype.preview = function () {
45796                         this.modalOption.templateUrl = 'templates/preview.html';
45797                         this.modalOption.controller = 'previewController';
45798                         this.modalOption.controllerAs = 'c';
45799                         this.modalOption.size = 'lg';
45800                         return this.$uibModal.open(this.modalOption);
45801                     };
45802                     MyModal.prototype.upload = function () {
45803                         this.modalOption.templateUrl = 'templates/upload.html';
45804                         this.modalOption.controller = 'uploadController';
45805                         this.modalOption.controllerAs = 'c';
45806                         this.modalOption.size = 'lg';
45807                         return this.$uibModal.open(this.modalOption);
45808                     };
45809                     MyModal.$inject = ['$uibModal'];
45810                     return MyModal;
45811                 })();
45812                 services.MyModal = MyModal;
45813             })(services = app.services || (app.services = {}));
45814         })(app || (app = {}));
45815         var app;
45816         (function (app) {
45817             var services;
45818             (function (services) {
45819                 var WebSocket = (function () {
45820                     function WebSocket($rootScope) {
45821                         this.$rootScope = $rootScope;
45822                         this.socket = io.connect();
45823                     }
45824                     WebSocket.prototype.on = function (eventName, callback) {
45825                         var socket = this.socket;
45826                         var rootScope = this.$rootScope;
45827                         socket.on(eventName, function () {
45828                             var args = arguments;
45829                             rootScope.$apply(function () {
45830                                 callback.apply(socket, args);
45831                             });
45832                         });
45833                     };
45834                     WebSocket.prototype.emit = function (eventName, data, callback) {
45835                         var socket = this.socket;
45836                         var rootScope = this.$rootScope;
45837                         this.socket.emit(eventName, data, function () {
45838                             var args = arguments;
45839                             rootScope.$apply(function () {
45840                                 if (callback)
45841                                     callback.apply(socket, args);
45842                             });
45843                         });
45844                     };
45845                     return WebSocket;
45846                 })();
45847                 services.WebSocket = WebSocket;
45848             })(services = app.services || (app.services = {}));
45849         })(app || (app = {}));
45850         var app;
45851         (function (app) {
45852             var services;
45853             (function (services) {
45854                 var Console = (function () {
45855                     function Console(WebSocket, $rootScope) {
45856                         this.WebSocket = WebSocket;
45857                         this.$rootScope = $rootScope;
45858                         this.WebSocket = WebSocket;
45859                         this.$rootScope = $rootScope;
45860                         this.directiveIDs = [];
45861                         var directiveIDs = this.directiveIDs;
45862                         this.WebSocket.on('console', function (d) {
45863                             var id = d.id;
45864                             var message = d.message;
45865                             if (directiveIDs.indexOf(id) > -1) {
45866                                 $rootScope.$emit(id, message);
45867                             }
45868                         });
45869                     }
45870                     Console.prototype.addDirective = function (id) {
45871                         if (!(this.directiveIDs.indexOf(id) > -1)) {
45872                             this.directiveIDs.push(id);
45873                         }
45874                     };
45875                     Console.prototype.removeDirective = function (id) {
45876                         var i = this.directiveIDs.indexOf(id);
45877                         if (i > -1) {
45878                             this.directiveIDs.splice(i, 1);
45879                         }
45880                     };
45881                     Console.prototype.showIDs = function () {
45882                         console.log(this.directiveIDs);
45883                     };
45884                     return Console;
45885                 })();
45886                 services.Console = Console;
45887             })(services = app.services || (app.services = {}));
45888         })(app || (app = {}));
45889         var app;
45890         (function (app) {
45891             var directives;
45892             (function (directives) {
45893                 var Command = (function () {
45894                     function Command() {
45895                         this.restrict = 'E';
45896                         this.replace = true;
45897                         this.scope = true;
45898                         this.controller = 'commandController';
45899                         this.controllerAs = 'ctrl';
45900                         this.bindToController = {
45901                             index: '=',
45902                             name: '=',
45903                             remove: '&',
45904                             list: '='
45905                         };
45906                         this.templateUrl = 'templates/command.html';
45907                     }
45908                     Command.Factory = function () {
45909                         var directive = function () {
45910                             return new Command();
45911                         };
45912                         directive.$inject = [];
45913                         return directive;
45914                     };
45915                     return Command;
45916                 })();
45917                 directives.Command = Command;
45918                 var CommandController = (function () {
45919                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
45920                         this.APIEndPoint = APIEndPoint;
45921                         this.$scope = $scope;
45922                         this.MyModal = MyModal;
45923                         this.WebSocket = WebSocket;
45924                         this.$window = $window;
45925                         this.$rootScope = $rootScope;
45926                         this.Console = Console;
45927                         var controller = this;
45928                         this.APIEndPoint
45929                             .getOptionControlFile(this.name)
45930                             .$promise
45931                             .then(function (result) {
45932                             controller.options = result.info;
45933                         });
45934                         this.APIEndPoint
45935                             .getDirectories()
45936                             .$promise
45937                             .then(function (result) {
45938                             controller.dirs = result.info;
45939                         });
45940                         this.heading = "[" + this.index + "]: dcdFilePrint";
45941                         this.isOpen = true;
45942                         this.$scope.$on('close', function () {
45943                             controller.isOpen = false;
45944                         });
45945                         function guid() {
45946                             function s4() {
45947                                 return Math.floor((1 + Math.random()) * 0x10000)
45948                                     .toString(16)
45949                                     .substring(1);
45950                             }
45951                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
45952                                 s4() + '-' + s4() + s4() + s4();
45953                         }
45954                         this.uuid = guid();
45955                         this.Console.addDirective(this.uuid);
45956                         this.Console.showIDs();
45957                     }
45958                     CommandController.prototype.submit = function () {
45959                         var opt = [];
45960                         angular.forEach(this.options, function (option) {
45961                             var obj = {
45962                                 name: option.option,
45963                                 arguments: []
45964                             };
45965                             angular.forEach(option.arg, function (arg) {
45966                                 if (arg.input) {
45967                                     if (typeof arg.input === 'object') {
45968                                         obj.arguments.push(arg.input.name);
45969                                     }
45970                                     else {
45971                                         obj.arguments.push(arg.input);
45972                                     }
45973                                 }
45974                             });
45975                             if (obj.arguments.length > 0) {
45976                                 opt.push(obj);
45977                             }
45978                         });
45979                         var execObj = {
45980                             command: this.name,
45981                             workspace: this.workspace.fileId,
45982                             options: opt
45983                         };
45984                         this.APIEndPoint
45985                             .execute(JSON.stringify(execObj))
45986                             .then(function (result) {
45987                             console.log(result);
45988                         });
45989                     };
45990                     CommandController.prototype.removeMySelf = function (index) {
45991                         this.$scope.$destroy();
45992                         this.Console.removeDirective(this.uuid);
45993                         this.remove()(index, this.list);
45994                         this.Console.showIDs();
45995                     };
45996                     CommandController.prototype.reloadFiles = function () {
45997                         var _this = this;
45998                         var fileId = this.workspace.fileId;
45999                         this.APIEndPoint
46000                             .getFiles(fileId)
46001                             .$promise
46002                             .then(function (result) {
46003                             var status = result.status;
46004                             if (status === 'success') {
46005                                 _this.files = result.info;
46006                             }
46007                             else {
46008                                 console.log(result.message);
46009                             }
46010                         });
46011                     };
46012                     CommandController.prototype.debug = function () {
46013                         var div = angular.element(this.$window.document).find("div");
46014                         var consoleTag;
46015                         var parametersTag;
46016                         angular.forEach(div, function (v) {
46017                             if (v.className === "panel-body console") {
46018                                 consoleTag = v;
46019                             }
46020                             else if (v.className === "row parameters-console") {
46021                                 parametersTag = v;
46022                             }
46023                         });
46024                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
46025                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
46026                         consoleTag.style.height = consoleHeight;
46027                         consoleTag.style.width = consoleWidth;
46028                     };
46029                     CommandController.prototype.help = function () {
46030                         this.APIEndPoint
46031                             .help(this.name)
46032                             .then(function (result) {
46033                             console.log(result);
46034                         });
46035                     };
46036                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
46037                     return CommandController;
46038                 })();
46039                 directives.CommandController = CommandController;
46040             })(directives = app.directives || (app.directives = {}));
46041         })(app || (app = {}));
46042         var app;
46043         (function (app) {
46044             var directives;
46045             (function (directives) {
46046                 var HeaderMenu = (function () {
46047                     function HeaderMenu() {
46048                         this.restrict = 'E';
46049                         this.replace = true;
46050                         this.templateUrl = 'templates/header-menu.html';
46051                         this.controller = 'HeaderMenuController';
46052                         this.controllerAs = 'hmc';
46053                         this.scope = true;
46054                     }
46055                     HeaderMenu.Factory = function () {
46056                         var directive = function () {
46057                             return new HeaderMenu();
46058                         };
46059                         return directive;
46060                     };
46061                     return HeaderMenu;
46062                 })();
46063                 directives.HeaderMenu = HeaderMenu;
46064                 var HeaderMenuController = (function () {
46065                     function HeaderMenuController($state) {
46066                         this.$state = $state;
46067                         this.isExecution = this.$state.current.name === 'execution';
46068                         this.isWorkspace = this.$state.current.name === 'workspace';
46069                         this.isHistory = this.$state.current.name === 'history';
46070                     }
46071                     HeaderMenuController.prototype.transit = function (state) {
46072                         this.$state.go(state);
46073                     };
46074                     HeaderMenuController.$inject = ['$state'];
46075                     return HeaderMenuController;
46076                 })();
46077                 directives.HeaderMenuController = HeaderMenuController;
46078             })(directives = app.directives || (app.directives = {}));
46079         })(app || (app = {}));
46080         var app;
46081         (function (app) {
46082             var directives;
46083             (function (directives) {
46084                 var Option = (function () {
46085                     function Option() {
46086                         this.restrict = 'E';
46087                         this.replace = true;
46088                         this.controller = 'optionController';
46089                         this.bindToController = {
46090                             info: '=',
46091                             files: '='
46092                         };
46093                         this.scope = true;
46094                         this.templateUrl = 'templates/option.html';
46095                         this.controllerAs = 'ctrl';
46096                     }
46097                     Option.Factory = function () {
46098                         var directive = function () {
46099                             return new Option();
46100                         };
46101                         directive.$inject = [];
46102                         return directive;
46103                     };
46104                     return Option;
46105                 })();
46106                 directives.Option = Option;
46107                 var OptionController = (function () {
46108                     function OptionController() {
46109                         var controller = this;
46110                         angular.forEach(controller.info.arg, function (arg) {
46111                             if (arg.initialValue) {
46112                                 if (arg.formType === 'number') {
46113                                     arg.input = parseInt(arg.initialValue);
46114                                 }
46115                                 else {
46116                                     arg.input = arg.initialValue;
46117                                 }
46118                             }
46119                         });
46120                     }
46121                     OptionController.$inject = [];
46122                     return OptionController;
46123                 })();
46124                 directives.OptionController = OptionController;
46125             })(directives = app.directives || (app.directives = {}));
46126         })(app || (app = {}));
46127         var app;
46128         (function (app) {
46129             var directives;
46130             (function (directives) {
46131                 var Directory = (function () {
46132                     function Directory() {
46133                         this.restrict = 'E';
46134                         this.replace = true;
46135                         this.controller = 'directoryController';
46136                         this.controllerAs = 'ctrl';
46137                         this.bindToController = {
46138                             info: '=',
46139                             add: '&',
46140                             list: '=',
46141                             files: '='
46142                         };
46143                         this.templateUrl = 'templates/directory.html';
46144                     }
46145                     Directory.Factory = function () {
46146                         var directive = function () {
46147                             return new Directory();
46148                         };
46149                         return directive;
46150                     };
46151                     return Directory;
46152                 })();
46153                 directives.Directory = Directory;
46154                 var DirectoryController = (function () {
46155                     function DirectoryController(APIEndPoint, $scope) {
46156                         this.APIEndPoint = APIEndPoint;
46157                         this.$scope = $scope;
46158                         var controller = this;
46159                         this.APIEndPoint
46160                             .getFiles(this.info.fileId)
46161                             .$promise
46162                             .then(function (result) {
46163                             if (result.status === 'success') {
46164                                 controller.files = result.info;
46165                                 angular.forEach(result.info, function (file) {
46166                                     if (file.fileType === '0') {
46167                                         var o = file;
46168                                         if (controller.info.path === '/') {
46169                                             o.path = '/' + file.name;
46170                                         }
46171                                         else {
46172                                             o.path = controller.info.path + '/' + file.name;
46173                                         }
46174                                         controller.add()(o, controller.list);
46175                                     }
46176                                 });
46177                             }
46178                             ;
46179                         });
46180                     }
46181                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
46182                     return DirectoryController;
46183                 })();
46184                 directives.DirectoryController = DirectoryController;
46185             })(directives = app.directives || (app.directives = {}));
46186         })(app || (app = {}));
46187         var app;
46188         (function (app) {
46189             var directives;
46190             (function (directives) {
46191                 var Upload = (function () {
46192                     function Upload() {
46193                         this.restrict = 'E';
46194                         this.replace = true;
46195                         this.scope = true;
46196                         this.controller = 'UploadController';
46197                         this.controllerAs = 'ctrl';
46198                         this.bindToController = {
46199                             index: '=',
46200                             name: '=',
46201                             remove: '&',
46202                             list: '='
46203                         };
46204                         this.templateUrl = 'templates/upload.html';
46205                         console.log("templates/upload.html-constructor");
46206                     }
46207                     Upload.Factory = function () {
46208                         var directive = function () {
46209                             return new Upload();
46210                         };
46211                         directive.$inject = [];
46212                         return directive;
46213                     };
46214                     return Upload;
46215                 })();
46216                 directives.Upload = Upload;
46217                 var UploadController = (function () {
46218                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
46219                         this.APIEndPoint = APIEndPoint;
46220                         this.$scope = $scope;
46221                         this.MyModal = MyModal;
46222                         this.WebSocket = WebSocket;
46223                         this.$window = $window;
46224                         this.$rootScope = $rootScope;
46225                         this.Console = Console;
46226                         var controller = this;
46227                         console.log("directive.upload-constructor");
46228                     }
46229                     UploadController.prototype.submit = function () {
46230                         console.log("submit: function not supported¥n");
46231                     };
46232                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
46233                     return UploadController;
46234                 })();
46235                 directives.UploadController = UploadController;
46236             })(directives = app.directives || (app.directives = {}));
46237         })(app || (app = {}));
46238         var app;
46239         (function (app) {
46240             var controllers;
46241             (function (controllers) {
46242                 var Execution = (function () {
46243                     function Execution(MyModal, $scope) {
46244                         this.MyModal = MyModal;
46245                         this.$scope = $scope;
46246                         this.commandInfoList = [];
46247                     }
46248                     ;
46249                     Execution.prototype.add = function () {
46250                         this.$scope.$broadcast('close');
46251                         var commandInfoList = this.commandInfoList;
46252                         var commandInstance = this.MyModal.selectCommand();
46253                         commandInstance
46254                             .result
46255                             .then(function (command) {
46256                             commandInfoList.push(new app.declares.CommandInfo(command));
46257                         });
46258                     };
46259                     Execution.prototype.open = function () {
46260                         var result = this.MyModal.open('SelectCommand');
46261                         console.log(result);
46262                     };
46263                     Execution.prototype.remove = function (index, list) {
46264                         list.splice(index, 1);
46265                     };
46266                     Execution.prototype.close = function () {
46267                         console.log("close");
46268                     };
46269                     Execution.$inject = ['MyModal', '$scope'];
46270                     return Execution;
46271                 })();
46272                 controllers.Execution = Execution;
46273             })(controllers = app.controllers || (app.controllers = {}));
46274         })(app || (app = {}));
46275         var app;
46276         (function (app) {
46277             var controllers;
46278             (function (controllers) {
46279                 var Workspace = (function () {
46280                     function Workspace($scope, APIEndPoint, MyModal) {
46281                         this.$scope = $scope;
46282                         this.APIEndPoint = APIEndPoint;
46283                         this.MyModal = MyModal;
46284                         this.directoryList = [];
46285                         var controller = this;
46286                         var directoryList = this.directoryList;
46287                         var o = {
46288                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
46289                             name: '',
46290                             parentId: '',
46291                             fileType: '',
46292                             createdAt: '',
46293                             updatedAt: '',
46294                             path: '/'
46295                         };
46296                         directoryList.push(o);
46297                     }
46298                     Workspace.prototype.addDirectory = function (info, directoryList) {
46299                         directoryList.push(info);
46300                     };
46301                     Workspace.prototype.upload = function () {
46302                         this.MyModal.upload();
46303                     };
46304                     Workspace.prototype.debug = function () {
46305                         this.MyModal.preview();
46306                     };
46307                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
46308                     return Workspace;
46309                 })();
46310                 controllers.Workspace = Workspace;
46311             })(controllers = app.controllers || (app.controllers = {}));
46312         })(app || (app = {}));
46313         var app;
46314         (function (app) {
46315             var controllers;
46316             (function (controllers) {
46317                 var History = (function () {
46318                     function History($scope) {
46319                         this.page = "History";
46320                     }
46321                     History.$inject = ['$scope'];
46322                     return History;
46323                 })();
46324                 controllers.History = History;
46325             })(controllers = app.controllers || (app.controllers = {}));
46326         })(app || (app = {}));
46327         var app;
46328         (function (app) {
46329             var controllers;
46330             (function (controllers) {
46331                 var SelectCommand = (function () {
46332                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
46333                         this.APIEndPoint = APIEndPoint;
46334                         this.$modalInstance = $modalInstance;
46335                         var controller = this;
46336                         this.APIEndPoint
46337                             .getTags()
46338                             .$promise.then(function (result) {
46339                             controller.tags = result.info;
46340                         });
46341                         this.APIEndPoint
46342                             .getCommands()
46343                             .$promise.then(function (result) {
46344                             controller.commands = result.info;
46345                         });
46346                         this.currentTag = 'all';
46347                     }
46348                     SelectCommand.prototype.changeTag = function (tag) {
46349                         this.currentTag = tag;
46350                     };
46351                     SelectCommand.prototype.selectCommand = function (command) {
46352                         this.$modalInstance.close(command);
46353                     };
46354                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
46355                     return SelectCommand;
46356                 })();
46357                 controllers.SelectCommand = SelectCommand;
46358             })(controllers = app.controllers || (app.controllers = {}));
46359         })(app || (app = {}));
46360         var app;
46361         (function (app) {
46362             var controllers;
46363             (function (controllers) {
46364                 var Upload = (function () {
46365                     function Upload($scope, APIEndPoint, $modalInstance) {
46366                         this.APIEndPoint = APIEndPoint;
46367                         this.$modalInstance = $modalInstance;
46368                         var controller = this;
46369                         console.log('controller.upload-controllers');
46370                     }
46371                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
46372                     return Upload;
46373                 })();
46374                 controllers.Upload = Upload;
46375             })(controllers = app.controllers || (app.controllers = {}));
46376         })(app || (app = {}));
46377         var app;
46378         (function (app) {
46379             var controllers;
46380             (function (controllers) {
46381                 var Preview = (function () {
46382                     function Preview($scope, APIEndPoint, $modalInstance) {
46383                         this.APIEndPoint = APIEndPoint;
46384                         this.$modalInstance = $modalInstance;
46385                         var controller = this;
46386                         console.log('preview');
46387                     }
46388                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
46389                     return Preview;
46390                 })();
46391                 controllers.Preview = Preview;
46392             })(controllers = app.controllers || (app.controllers = {}));
46393         })(app || (app = {}));
46394         var filters;
46395         (function (filters) {
46396             function Tag() {
46397                 return function (commands, tag) {
46398                     var result = [];
46399                     angular.forEach(commands, function (command) {
46400                         var flag = false;
46401                         angular.forEach(command.tags, function (value) {
46402                             if (tag === value)
46403                                 flag = true;
46404                         });
46405                         if (flag)
46406                             result.push(command);
46407                     });
46408                     return result;
46409                 };
46410             }
46411             filters.Tag = Tag;
46412         })(filters || (filters = {}));
46413         var app;
46414         (function (app) {
46415             'use strict';
46416             var appName = 'zephyr';
46417             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
46418             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
46419                 $urlRouterProvider.otherwise('/execution');
46420                 $locationProvider.html5Mode({
46421                     enabled: true,
46422                     requireBase: false
46423                 });
46424                 $stateProvider
46425                     .state('execution', {
46426                     url: '/execution',
46427                     templateUrl: 'templates/execution.html',
46428                     controller: 'executionController',
46429                     controllerAs: 'c'
46430                 })
46431                     .state('workspace', {
46432                     url: '/workspace',
46433                     templateUrl: 'templates/workspace.html',
46434                     controller: 'workspaceController',
46435                     controllerAs: 'c'
46436                 })
46437                     .state('history', {
46438                     url: '/history',
46439                     templateUrl: 'templates/history.html',
46440                     controller: 'historyController',
46441                     controllerAs: 'c'
46442                 });
46443             });
46444             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
46445             app.zephyr.service('MyModal', app.services.MyModal);
46446             app.zephyr.service('WebSocket', app.services.WebSocket);
46447             app.zephyr.service('Console', app.services.Console);
46448             app.zephyr.filter('Tag', filters.Tag);
46449             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
46450             app.zephyr.controller('previewController', app.controllers.Preview);
46451             app.zephyr.controller('uploadController', app.controllers.Upload);
46452             app.zephyr.controller('executionController', app.controllers.Execution);
46453             app.zephyr.controller('workspaceController', app.controllers.Workspace);
46454             app.zephyr.controller('historyController', app.controllers.History);
46455             app.zephyr.controller('commandController', app.directives.CommandController);
46456             app.zephyr.controller('optionController', app.directives.OptionController);
46457             app.zephyr.controller('directoryController', app.directives.DirectoryController);
46458             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
46459             app.zephyr.controller('uploadController', app.directives.UploadController);
46460             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
46461             app.zephyr.directive('command', app.directives.Command.Factory());
46462             app.zephyr.directive('option', app.directives.Option.Factory());
46463             app.zephyr.directive('directory', app.directives.Directory.Factory());
46464         })(app || (app = {}));
46465
46466
46467 /***/ },
46468 /* 10 */
46469 =======
46470                 return attrs.popupTemplateUrl || 'uib/template/typeahead/typeahead-popup.html';
46471               },
46472               link: function(scope, element, attrs) {
46473                 scope.templateUrl = attrs.templateUrl;
46474
46475                 scope.isOpen = function() {
46476                   var isDropdownOpen = scope.matches.length > 0;
46477                   scope.assignIsOpen({ isOpen: isDropdownOpen });
46478                   return isDropdownOpen;
46479                 };
46480
46481                 scope.isActive = function(matchIdx) {
46482                   return scope.active === matchIdx;
46483                 };
46484
46485                 scope.selectActive = function(matchIdx) {
46486                   scope.active = matchIdx;
46487                 };
46488
46489                 scope.selectMatch = function(activeIdx, evt) {
46490                   var debounce = scope.debounce();
46491                   if (angular.isNumber(debounce) || angular.isObject(debounce)) {
46492                     $$debounce(function() {
46493                       scope.select({activeIdx: activeIdx, evt: evt});
46494                     }, angular.isNumber(debounce) ? debounce : debounce['default']);
46495                   } else {
46496                     scope.select({activeIdx: activeIdx, evt: evt});
46497                   }
46498                 };
46499               }
46500             };
46501           }])
46502
46503           .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function($templateRequest, $compile, $parse) {
46504             return {
46505               scope: {
46506                 index: '=',
46507                 match: '=',
46508                 query: '='
46509               },
46510               link: function(scope, element, attrs) {
46511                 var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'uib/template/typeahead/typeahead-match.html';
46512                 $templateRequest(tplUrl).then(function(tplContent) {
46513                   var tplEl = angular.element(tplContent.trim());
46514                   element.replaceWith(tplEl);
46515                   $compile(tplEl)(scope);
46516                 });
46517               }
46518             };
46519           }])
46520
46521           .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function($sce, $injector, $log) {
46522             var isSanitizePresent;
46523             isSanitizePresent = $injector.has('$sanitize');
46524
46525             function escapeRegexp(queryToEscape) {
46526               // Regex: capture the whole query string and replace it with the string that will be used to match
46527               // the results, for example if the capture is "a" the result will be \a
46528               return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
46529             }
46530
46531             function containsHtml(matchItem) {
46532               return /<.*>/g.test(matchItem);
46533             }
46534
46535             return function(matchItem, query) {
46536               if (!isSanitizePresent && containsHtml(matchItem)) {
46537                 $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger
46538               }
46539               matchItem = query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem; // Replaces the capture string with a the same string inside of a "strong" tag
46540               if (!isSanitizePresent) {
46541                 matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive
46542               }
46543               return matchItem;
46544             };
46545           }]);
46546
46547         angular.module("uib/template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
46548           $templateCache.put("uib/template/accordion/accordion-group.html",
46549             "<div class=\"panel\" ng-class=\"panelClass || 'panel-default'\">\n" +
46550             "  <div class=\"panel-heading\" ng-keypress=\"toggleOpen($event)\">\n" +
46551             "    <h4 class=\"panel-title\">\n" +
46552             "      <div tabindex=\"0\" class=\"accordion-toggle\" ng-click=\"toggleOpen()\" uib-accordion-transclude=\"heading\"><span ng-class=\"{'text-muted': isDisabled}\">{{heading}}</span></div>\n" +
46553             "    </h4>\n" +
46554             "  </div>\n" +
46555             "  <div class=\"panel-collapse collapse\" uib-collapse=\"!isOpen\">\n" +
46556             "     <div class=\"panel-body\" ng-transclude></div>\n" +
46557             "  </div>\n" +
46558             "</div>\n" +
46559             "");
46560         }]);
46561
46562         angular.module("uib/template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
46563           $templateCache.put("uib/template/accordion/accordion.html",
46564             "<div class=\"panel-group\" ng-transclude></div>");
46565         }]);
46566
46567         angular.module("uib/template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
46568           $templateCache.put("uib/template/alert/alert.html",
46569             "<div class=\"alert\" ng-class=\"['alert-' + (type || 'warning'), closeable ? 'alert-dismissible' : null]\" role=\"alert\">\n" +
46570             "    <button ng-show=\"closeable\" type=\"button\" class=\"close\" ng-click=\"close({$event: $event})\">\n" +
46571             "        <span aria-hidden=\"true\">&times;</span>\n" +
46572             "        <span class=\"sr-only\">Close</span>\n" +
46573             "    </button>\n" +
46574             "    <div ng-transclude></div>\n" +
46575             "</div>\n" +
46576             "");
46577         }]);
46578
46579         angular.module("uib/template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
46580           $templateCache.put("uib/template/carousel/carousel.html",
46581             "<div ng-mouseenter=\"pause()\" ng-mouseleave=\"play()\" class=\"carousel\" ng-swipe-right=\"prev()\" ng-swipe-left=\"next()\">\n" +
46582             "  <div class=\"carousel-inner\" ng-transclude></div>\n" +
46583             "  <a role=\"button\" href class=\"left carousel-control\" ng-click=\"prev()\" ng-show=\"slides.length > 1\">\n" +
46584             "    <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></span>\n" +
46585             "    <span class=\"sr-only\">previous</span>\n" +
46586             "  </a>\n" +
46587             "  <a role=\"button\" href class=\"right carousel-control\" ng-click=\"next()\" ng-show=\"slides.length > 1\">\n" +
46588             "    <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></span>\n" +
46589             "    <span class=\"sr-only\">next</span>\n" +
46590             "  </a>\n" +
46591             "  <ol class=\"carousel-indicators\" ng-show=\"slides.length > 1\">\n" +
46592             "    <li ng-repeat=\"slide in slides | orderBy:indexOfSlide track by $index\" ng-class=\"{ active: isActive(slide) }\" ng-click=\"select(slide)\">\n" +
46593             "      <span class=\"sr-only\">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if=\"isActive(slide)\">, currently active</span></span>\n" +
46594             "    </li>\n" +
46595             "  </ol>\n" +
46596             "</div>");
46597         }]);
46598
46599         angular.module("uib/template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
46600           $templateCache.put("uib/template/carousel/slide.html",
46601             "<div ng-class=\"{\n" +
46602             "    'active': active\n" +
46603             "  }\" class=\"item text-center\" ng-transclude></div>\n" +
46604             "");
46605         }]);
46606
46607         angular.module("uib/template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
46608           $templateCache.put("uib/template/datepicker/datepicker.html",
46609             "<div class=\"uib-datepicker\" ng-switch=\"datepickerMode\" role=\"application\" ng-keydown=\"keydown($event)\">\n" +
46610             "  <uib-daypicker ng-switch-when=\"day\" tabindex=\"0\"></uib-daypicker>\n" +
46611             "  <uib-monthpicker ng-switch-when=\"month\" tabindex=\"0\"></uib-monthpicker>\n" +
46612             "  <uib-yearpicker ng-switch-when=\"year\" tabindex=\"0\"></uib-yearpicker>\n" +
46613             "</div>");
46614         }]);
46615
46616         angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", function($templateCache) {
46617           $templateCache.put("uib/template/datepicker/day.html",
46618             "<table class=\"uib-daypicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
46619             "  <thead>\n" +
46620             "    <tr>\n" +
46621             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
46622             "      <th colspan=\"{{::5 + showWeeks}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\" style=\"width:100%;\"><strong>{{title}}</strong></button></th>\n" +
46623             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
46624             "    </tr>\n" +
46625             "    <tr>\n" +
46626             "      <th ng-if=\"showWeeks\" class=\"text-center\"></th>\n" +
46627             "      <th ng-repeat=\"label in ::labels track by $index\" class=\"text-center\"><small aria-label=\"{{::label.full}}\">{{::label.abbr}}</small></th>\n" +
46628             "    </tr>\n" +
46629             "  </thead>\n" +
46630             "  <tbody>\n" +
46631             "    <tr class=\"uib-weeks\" ng-repeat=\"row in rows track by $index\">\n" +
46632             "      <td ng-if=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
46633             "      <td ng-repeat=\"dt in row\" class=\"uib-day text-center\" role=\"gridcell\"\n" +
46634             "        id=\"{{::dt.uid}}\"\n" +
46635             "        ng-class=\"::dt.customClass\">\n" +
46636             "        <button type=\"button\" style=\"min-width:100%;\" class=\"btn btn-default btn-sm\"\n" +
46637             "          uib-is-class=\"\n" +
46638             "            'btn-info' for selectedDt,\n" +
46639             "            'active' for activeDt\n" +
46640             "            on dt\"\n" +
46641             "          ng-click=\"select(dt.date)\"\n" +
46642             "          ng-disabled=\"::dt.disabled\"\n" +
46643             "          tabindex=\"-1\"><span ng-class=\"::{'text-muted': dt.secondary, 'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
46644             "      </td>\n" +
46645             "    </tr>\n" +
46646             "  </tbody>\n" +
46647             "</table>\n" +
46648             "");
46649         }]);
46650
46651         angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", function($templateCache) {
46652           $templateCache.put("uib/template/datepicker/month.html",
46653             "<table class=\"uib-monthpicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
46654             "  <thead>\n" +
46655             "    <tr>\n" +
46656             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
46657             "      <th><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\" style=\"width:100%;\"><strong>{{title}}</strong></button></th>\n" +
46658             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
46659             "    </tr>\n" +
46660             "  </thead>\n" +
46661             "  <tbody>\n" +
46662             "    <tr class=\"uib-months\" ng-repeat=\"row in rows track by $index\">\n" +
46663             "      <td ng-repeat=\"dt in row\" class=\"uib-month text-center\" role=\"gridcell\"\n" +
46664             "        id=\"{{::dt.uid}}\"\n" +
46665             "        ng-class=\"::dt.customClass\">\n" +
46666             "        <button type=\"button\" style=\"min-width:100%;\" class=\"btn btn-default\"\n" +
46667             "          uib-is-class=\"\n" +
46668             "            'btn-info' for selectedDt,\n" +
46669             "            'active' for activeDt\n" +
46670             "            on dt\"\n" +
46671             "          ng-click=\"select(dt.date)\"\n" +
46672             "          ng-disabled=\"::dt.disabled\"\n" +
46673             "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
46674             "      </td>\n" +
46675             "    </tr>\n" +
46676             "  </tbody>\n" +
46677             "</table>\n" +
46678             "");
46679         }]);
46680
46681         angular.module("uib/template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) {
46682           $templateCache.put("uib/template/datepicker/popup.html",
46683             "<ul class=\"uib-datepicker-popup dropdown-menu\" dropdown-nested ng-if=\"isOpen\" style=\"display: block\" ng-style=\"{top: position.top+'px', left: position.left+'px'}\" ng-keydown=\"keydown($event)\" ng-click=\"$event.stopPropagation()\">\n" +
46684             "   <li ng-transclude></li>\n" +
46685             "   <li ng-if=\"showButtonBar\" style=\"padding:10px 9px 2px\" class=\"uib-button-bar\">\n" +
46686             "           <span class=\"btn-group pull-left\">\n" +
46687             "                   <button type=\"button\" class=\"btn btn-sm btn-info uib-datepicker-current\" ng-click=\"select('today')\" ng-disabled=\"isDisabled('today')\">{{ getText('current') }}</button>\n" +
46688             "                   <button type=\"button\" class=\"btn btn-sm btn-danger uib-clear\" ng-click=\"select(null)\">{{ getText('clear') }}</button>\n" +
46689             "           </span>\n" +
46690             "           <button type=\"button\" class=\"btn btn-sm btn-success pull-right uib-close\" ng-click=\"close()\">{{ getText('close') }}</button>\n" +
46691             "   </li>\n" +
46692             "</ul>\n" +
46693             "");
46694         }]);
46695
46696         angular.module("uib/template/datepicker/year.html", []).run(["$templateCache", function($templateCache) {
46697           $templateCache.put("uib/template/datepicker/year.html",
46698             "<table class=\"uib-yearpicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
46699             "  <thead>\n" +
46700             "    <tr>\n" +
46701             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
46702             "      <th colspan=\"{{::columns - 2}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\" style=\"width:100%;\"><strong>{{title}}</strong></button></th>\n" +
46703             "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
46704             "    </tr>\n" +
46705             "  </thead>\n" +
46706             "  <tbody>\n" +
46707             "    <tr class=\"uib-years\" ng-repeat=\"row in rows track by $index\">\n" +
46708             "      <td ng-repeat=\"dt in row\" class=\"uib-year text-center\" role=\"gridcell\"\n" +
46709             "        id=\"{{::dt.uid}}\"\n" +
46710             "        ng-class=\"::dt.customClass\">\n" +
46711             "        <button type=\"button\" style=\"min-width:100%;\" class=\"btn btn-default\"\n" +
46712             "          uib-is-class=\"\n" +
46713             "            'btn-info' for selectedDt,\n" +
46714             "            'active' for activeDt\n" +
46715             "            on dt\"\n" +
46716             "          ng-click=\"select(dt.date)\"\n" +
46717             "          ng-disabled=\"::dt.disabled\"\n" +
46718             "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
46719             "      </td>\n" +
46720             "    </tr>\n" +
46721             "  </tbody>\n" +
46722             "</table>\n" +
46723             "");
46724         }]);
46725
46726         angular.module("uib/template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
46727           $templateCache.put("uib/template/modal/backdrop.html",
46728             "<div class=\"modal-backdrop\"\n" +
46729             "     uib-modal-animation-class=\"fade\"\n" +
46730             "     modal-in-class=\"in\"\n" +
46731             "     ng-style=\"{'z-index': 1040 + (index && 1 || 0) + index*10}\"\n" +
46732             "></div>\n" +
46733             "");
46734         }]);
46735
46736         angular.module("uib/template/modal/window.html", []).run(["$templateCache", function($templateCache) {
46737           $templateCache.put("uib/template/modal/window.html",
46738             "<div modal-render=\"{{$isRendered}}\" tabindex=\"-1\" role=\"dialog\" class=\"modal\"\n" +
46739             "    uib-modal-animation-class=\"fade\"\n" +
46740             "    modal-in-class=\"in\"\n" +
46741             "    ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\">\n" +
46742             "    <div class=\"modal-dialog\" ng-class=\"size ? 'modal-' + size : ''\"><div class=\"modal-content\" uib-modal-transclude></div></div>\n" +
46743             "</div>\n" +
46744             "");
46745         }]);
46746
46747         angular.module("uib/template/pager/pager.html", []).run(["$templateCache", function($templateCache) {
46748           $templateCache.put("uib/template/pager/pager.html",
46749             "<ul class=\"pager\">\n" +
46750             "  <li ng-class=\"{disabled: noPrevious()||ngDisabled, previous: align}\"><a href ng-click=\"selectPage(page - 1, $event)\">{{::getText('previous')}}</a></li>\n" +
46751             "  <li ng-class=\"{disabled: noNext()||ngDisabled, next: align}\"><a href ng-click=\"selectPage(page + 1, $event)\">{{::getText('next')}}</a></li>\n" +
46752             "</ul>\n" +
46753             "");
46754         }]);
46755
46756         angular.module("uib/template/pagination/pager.html", []).run(["$templateCache", function($templateCache) {
46757           $templateCache.put("uib/template/pagination/pager.html",
46758             "<ul class=\"pager\">\n" +
46759             "  <li ng-class=\"{disabled: noPrevious()||ngDisabled, previous: align}\"><a href ng-click=\"selectPage(page - 1, $event)\">{{::getText('previous')}}</a></li>\n" +
46760             "  <li ng-class=\"{disabled: noNext()||ngDisabled, next: align}\"><a href ng-click=\"selectPage(page + 1, $event)\">{{::getText('next')}}</a></li>\n" +
46761             "</ul>\n" +
46762             "");
46763         }]);
46764
46765         angular.module("uib/template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
46766           $templateCache.put("uib/template/pagination/pagination.html",
46767             "<ul class=\"pagination\">\n" +
46768             "  <li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-first\"><a href ng-click=\"selectPage(1, $event)\">{{::getText('first')}}</a></li>\n" +
46769             "  <li ng-if=\"::directionLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-prev\"><a href ng-click=\"selectPage(page - 1, $event)\">{{::getText('previous')}}</a></li>\n" +
46770             "  <li ng-repeat=\"page in pages track by $index\" ng-class=\"{active: page.active,disabled: ngDisabled&&!page.active}\" class=\"pagination-page\"><a href ng-click=\"selectPage(page.number, $event)\">{{page.text}}</a></li>\n" +
46771             "  <li ng-if=\"::directionLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-next\"><a href ng-click=\"selectPage(page + 1, $event)\">{{::getText('next')}}</a></li>\n" +
46772             "  <li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-last\"><a href ng-click=\"selectPage(totalPages, $event)\">{{::getText('last')}}</a></li>\n" +
46773             "</ul>\n" +
46774             "");
46775         }]);
46776
46777         angular.module("uib/template/tooltip/tooltip-html-popup.html", []).run(["$templateCache", function($templateCache) {
46778           $templateCache.put("uib/template/tooltip/tooltip-html-popup.html",
46779             "<div class=\"tooltip\"\n" +
46780             "  tooltip-animation-class=\"fade\"\n" +
46781             "  uib-tooltip-classes\n" +
46782             "  ng-class=\"{ in: isOpen() }\">\n" +
46783             "  <div class=\"tooltip-arrow\"></div>\n" +
46784             "  <div class=\"tooltip-inner\" ng-bind-html=\"contentExp()\"></div>\n" +
46785             "</div>\n" +
46786             "");
46787         }]);
46788
46789         angular.module("uib/template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
46790           $templateCache.put("uib/template/tooltip/tooltip-popup.html",
46791             "<div class=\"tooltip\"\n" +
46792             "  tooltip-animation-class=\"fade\"\n" +
46793             "  uib-tooltip-classes\n" +
46794             "  ng-class=\"{ in: isOpen() }\">\n" +
46795             "  <div class=\"tooltip-arrow\"></div>\n" +
46796             "  <div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
46797             "</div>\n" +
46798             "");
46799         }]);
46800
46801         angular.module("uib/template/tooltip/tooltip-template-popup.html", []).run(["$templateCache", function($templateCache) {
46802           $templateCache.put("uib/template/tooltip/tooltip-template-popup.html",
46803             "<div class=\"tooltip\"\n" +
46804             "  tooltip-animation-class=\"fade\"\n" +
46805             "  uib-tooltip-classes\n" +
46806             "  ng-class=\"{ in: isOpen() }\">\n" +
46807             "  <div class=\"tooltip-arrow\"></div>\n" +
46808             "  <div class=\"tooltip-inner\"\n" +
46809             "    uib-tooltip-template-transclude=\"contentExp()\"\n" +
46810             "    tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
46811             "</div>\n" +
46812             "");
46813         }]);
46814
46815         angular.module("uib/template/popover/popover-html.html", []).run(["$templateCache", function($templateCache) {
46816           $templateCache.put("uib/template/popover/popover-html.html",
46817             "<div class=\"popover\"\n" +
46818             "  tooltip-animation-class=\"fade\"\n" +
46819             "  uib-tooltip-classes\n" +
46820             "  ng-class=\"{ in: isOpen() }\">\n" +
46821             "  <div class=\"arrow\"></div>\n" +
46822             "\n" +
46823             "  <div class=\"popover-inner\">\n" +
46824             "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-if=\"title\"></h3>\n" +
46825             "      <div class=\"popover-content\" ng-bind-html=\"contentExp()\"></div>\n" +
46826             "  </div>\n" +
46827             "</div>\n" +
46828             "");
46829         }]);
46830
46831         angular.module("uib/template/popover/popover-template.html", []).run(["$templateCache", function($templateCache) {
46832           $templateCache.put("uib/template/popover/popover-template.html",
46833             "<div class=\"popover\"\n" +
46834             "  tooltip-animation-class=\"fade\"\n" +
46835             "  uib-tooltip-classes\n" +
46836             "  ng-class=\"{ in: isOpen() }\">\n" +
46837             "  <div class=\"arrow\"></div>\n" +
46838             "\n" +
46839             "  <div class=\"popover-inner\">\n" +
46840             "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-if=\"title\"></h3>\n" +
46841             "      <div class=\"popover-content\"\n" +
46842             "        uib-tooltip-template-transclude=\"contentExp()\"\n" +
46843             "        tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
46844             "  </div>\n" +
46845             "</div>\n" +
46846             "");
46847         }]);
46848
46849         angular.module("uib/template/popover/popover.html", []).run(["$templateCache", function($templateCache) {
46850           $templateCache.put("uib/template/popover/popover.html",
46851             "<div class=\"popover\"\n" +
46852             "  tooltip-animation-class=\"fade\"\n" +
46853             "  uib-tooltip-classes\n" +
46854             "  ng-class=\"{ in: isOpen() }\">\n" +
46855             "  <div class=\"arrow\"></div>\n" +
46856             "\n" +
46857             "  <div class=\"popover-inner\">\n" +
46858             "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-if=\"title\"></h3>\n" +
46859             "      <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
46860             "  </div>\n" +
46861             "</div>\n" +
46862             "");
46863         }]);
46864
46865         angular.module("uib/template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
46866           $templateCache.put("uib/template/progressbar/bar.html",
46867             "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
46868             "");
46869         }]);
46870
46871         angular.module("uib/template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
46872           $templateCache.put("uib/template/progressbar/progress.html",
46873             "<div class=\"progress\" ng-transclude aria-labelledby=\"{{::title}}\"></div>");
46874         }]);
46875
46876         angular.module("uib/template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
46877           $templateCache.put("uib/template/progressbar/progressbar.html",
46878             "<div class=\"progress\">\n" +
46879             "  <div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
46880             "</div>\n" +
46881             "");
46882         }]);
46883
46884         angular.module("uib/template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
46885           $templateCache.put("uib/template/rating/rating.html",
46886             "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\">\n" +
46887             "    <span ng-repeat-start=\"r in range track by $index\" class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
46888             "    <i ng-repeat-end ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\" ng-attr-title=\"{{r.title}}\" aria-valuetext=\"{{r.title}}\"></i>\n" +
46889             "</span>\n" +
46890             "");
46891         }]);
46892
46893         angular.module("uib/template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
46894           $templateCache.put("uib/template/tabs/tab.html",
46895             "<li ng-class=\"{active: active, disabled: disabled}\" class=\"uib-tab\">\n" +
46896             "  <div ng-click=\"select()\" uib-tab-heading-transclude>{{heading}}</div>\n" +
46897             "</li>\n" +
46898             "");
46899         }]);
46900
46901         angular.module("uib/template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
46902           $templateCache.put("uib/template/tabs/tabset.html",
46903             "<div>\n" +
46904             "  <ul class=\"nav nav-{{type || 'tabs'}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
46905             "  <div class=\"tab-content\">\n" +
46906             "    <div class=\"tab-pane\" \n" +
46907             "         ng-repeat=\"tab in tabs\" \n" +
46908             "         ng-class=\"{active: tab.active}\"\n" +
46909             "         uib-tab-content-transclude=\"tab\">\n" +
46910             "    </div>\n" +
46911             "  </div>\n" +
46912             "</div>\n" +
46913             "");
46914         }]);
46915
46916         angular.module("uib/template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) {
46917           $templateCache.put("uib/template/timepicker/timepicker.html",
46918             "<table class=\"uib-timepicker\">\n" +
46919             "  <tbody>\n" +
46920             "    <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
46921             "      <td class=\"uib-increment hours\"><a ng-click=\"incrementHours()\" ng-class=\"{disabled: noIncrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementHours()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
46922             "      <td>&nbsp;</td>\n" +
46923             "      <td class=\"uib-increment minutes\"><a ng-click=\"incrementMinutes()\" ng-class=\"{disabled: noIncrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementMinutes()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
46924             "      <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
46925             "      <td ng-show=\"showSeconds\" class=\"uib-increment seconds\"><a ng-click=\"incrementSeconds()\" ng-class=\"{disabled: noIncrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementSeconds()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
46926             "      <td ng-show=\"showMeridian\"></td>\n" +
46927             "    </tr>\n" +
46928             "    <tr>\n" +
46929             "      <td class=\"form-group uib-time hours\" ng-class=\"{'has-error': invalidHours}\">\n" +
46930             "        <input style=\"width:50px;\" type=\"text\" placeholder=\"HH\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"disabled\" ng-blur=\"blur()\">\n" +
46931             "      </td>\n" +
46932             "      <td class=\"uib-separator\">:</td>\n" +
46933             "      <td class=\"form-group uib-time minutes\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
46934             "        <input style=\"width:50px;\" type=\"text\" placeholder=\"MM\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"disabled\" ng-blur=\"blur()\">\n" +
46935             "      </td>\n" +
46936             "      <td ng-show=\"showSeconds\" class=\"uib-separator\">:</td>\n" +
46937             "      <td class=\"form-group uib-time seconds\" ng-class=\"{'has-error': invalidSeconds}\" ng-show=\"showSeconds\">\n" +
46938             "        <input style=\"width:50px;\" type=\"text\" ng-model=\"seconds\" ng-change=\"updateSeconds()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"disabled\" ng-blur=\"blur()\">\n" +
46939             "      </td>\n" +
46940             "      <td ng-show=\"showMeridian\" class=\"uib-time am-pm\"><button type=\"button\" ng-class=\"{disabled: noToggleMeridian()}\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\" ng-disabled=\"noToggleMeridian()\" tabindex=\"{{::tabindex}}\">{{meridian}}</button></td>\n" +
46941             "    </tr>\n" +
46942             "    <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
46943             "      <td class=\"uib-decrement hours\"><a ng-click=\"decrementHours()\" ng-class=\"{disabled: noDecrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementHours()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
46944             "      <td>&nbsp;</td>\n" +
46945             "      <td class=\"uib-decrement minutes\"><a ng-click=\"decrementMinutes()\" ng-class=\"{disabled: noDecrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementMinutes()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
46946             "      <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
46947             "      <td ng-show=\"showSeconds\" class=\"uib-decrement seconds\"><a ng-click=\"decrementSeconds()\" ng-class=\"{disabled: noDecrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementSeconds()\" tabindex=\"{{::tabindex}}\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
46948             "      <td ng-show=\"showMeridian\"></td>\n" +
46949             "    </tr>\n" +
46950             "  </tbody>\n" +
46951             "</table>\n" +
46952             "");
46953         }]);
46954
46955         angular.module("uib/template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) {
46956           $templateCache.put("uib/template/typeahead/typeahead-match.html",
46957             "<a href tabindex=\"-1\" ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"></a>\n" +
46958             "");
46959         }]);
46960
46961         angular.module("uib/template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
46962           $templateCache.put("uib/template/typeahead/typeahead-popup.html",
46963             "<ul class=\"dropdown-menu\" ng-show=\"isOpen() && !moveInProgress\" ng-style=\"{top: position().top+'px', left: position().left+'px'}\" style=\"display: block;\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
46964             "    <li ng-repeat=\"match in matches track by $index\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index, $event)\" role=\"option\" id=\"{{::match.id}}\">\n" +
46965             "        <div uib-typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
46966             "    </li>\n" +
46967             "</ul>\n" +
46968             "");
46969         }]);
46970         angular.module('ui.bootstrap.carousel').run(function() {!angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'); })
46971
46972 /***/ },
46973 /* 8 */
46974 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
46975 /***/ function(module, exports) {
46976
46977         var app;
46978         (function (app) {
46979             var declares;
46980             (function (declares) {
46981                 var CommandInfo = (function () {
46982                     function CommandInfo(name) {
46983                         this.name = name;
46984                     }
46985                     return CommandInfo;
46986                 })();
46987                 declares.CommandInfo = CommandInfo;
46988             })(declares = app.declares || (app.declares = {}));
46989         })(app || (app = {}));
46990         var app;
46991         (function (app) {
46992             var services;
46993             (function (services) {
46994                 var APIEndPoint = (function () {
46995                     function APIEndPoint($resource, $http) {
46996                         this.$resource = $resource;
46997                         this.$http = $http;
46998                     }
46999                     APIEndPoint.prototype.resource = function (endPoint, data) {
47000                         var customAction = {
47001                             method: 'GET',
47002                             isArray: false
47003                         };
47004                         var execute = {
47005                             method: 'POST',
47006                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
47007                         };
47008                         return this.$resource(endPoint, {}, { execute: execute });
47009                     };
47010                     APIEndPoint.prototype.getOptionControlFile = function (command) {
47011                         var endPoint = '/api/v1/optionControlFile/' + command;
47012                         return this.resource(endPoint, {}).get();
47013                     };
47014                     APIEndPoint.prototype.getFiles = function (fileId) {
47015                         var endPoint = '/api/v1/workspace';
47016                         if (fileId) {
47017                             endPoint += '/' + fileId;
47018                         }
47019                         return this.resource(endPoint, {}).get();
47020                     };
47021                     APIEndPoint.prototype.getDirectories = function () {
47022                         var endPoint = '/api/v1/all/workspace/directory';
47023                         return this.resource(endPoint, {}).get();
47024                     };
47025                     APIEndPoint.prototype.getTags = function () {
47026                         var endPoint = '/api/v1/tagList';
47027                         return this.resource(endPoint, {}).get();
47028                     };
47029                     APIEndPoint.prototype.getCommands = function () {
47030                         var endPoint = '/api/v1/commandList';
47031                         return this.resource(endPoint, {}).get();
47032                     };
47033                     APIEndPoint.prototype.execute = function (data) {
47034                         var endPoint = '/api/v1/execution';
47035                         var fd = new FormData();
47036                         fd.append('data', data);
47037                         return this.$http.post(endPoint, fd, {
47038                             headers: { 'Content-Type': undefined },
47039                             transformRequest: angular.identity
47040                         });
47041                     };
47042                     APIEndPoint.prototype.debug = function () {
47043                         var endPoint = '/api/v1/debug';
47044                         return this.$http.get(endPoint);
47045                     };
47046 <<<<<<< HEAD
47047                     APIEndPoint.prototype.upload = function () {
47048                         var endPoint = '/api/v1/upload';
47049                         return this.$http.get(endPoint);
47050                     };
47051 =======
47052 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47053                     APIEndPoint.prototype.help = function (command) {
47054                         var endPoint = '/api/v1/help/' + command;
47055                         return this.$http.get(endPoint);
47056                     };
47057                     return APIEndPoint;
47058                 })();
47059                 services.APIEndPoint = APIEndPoint;
47060             })(services = app.services || (app.services = {}));
47061         })(app || (app = {}));
47062         var app;
47063         (function (app) {
47064             var services;
47065             (function (services) {
47066                 var MyModal = (function () {
47067                     function MyModal($uibModal) {
47068                         this.$uibModal = $uibModal;
47069                         this.modalOption = {
47070                             backdrop: true,
47071                             controller: null,
47072                             templateUrl: null,
47073                             size: null
47074                         };
47075                     }
47076                     MyModal.prototype.open = function (modalName) {
47077                         if (modalName === 'SelectCommand') {
47078                             this.modalOption.templateUrl = 'templates/select-command.html';
47079                             this.modalOption.size = 'lg';
47080                         }
47081                         return this.$uibModal.open(this.modalOption);
47082                     };
47083                     MyModal.prototype.selectCommand = function () {
47084                         this.modalOption.templateUrl = 'templates/select-command.html';
47085                         this.modalOption.controller = 'selectCommandController';
47086                         this.modalOption.controllerAs = 'c';
47087                         this.modalOption.size = 'lg';
47088                         return this.$uibModal.open(this.modalOption);
47089                     };
47090                     MyModal.prototype.preview = function () {
47091                         this.modalOption.templateUrl = 'templates/preview.html';
47092                         this.modalOption.controller = 'previewController';
47093                         this.modalOption.controllerAs = 'c';
47094                         this.modalOption.size = 'lg';
47095                         return this.$uibModal.open(this.modalOption);
47096                     };
47097 <<<<<<< HEAD
47098                     MyModal.prototype.upload = function () {
47099                         this.modalOption.templateUrl = 'templates/upload.html';
47100                         this.modalOption.controller = 'uploadController';
47101                         this.modalOption.controllerAs = 'c';
47102                         this.modalOption.size = 'lg';
47103                         return this.$uibModal.open(this.modalOption);
47104                     };
47105 =======
47106 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47107                     MyModal.$inject = ['$uibModal'];
47108                     return MyModal;
47109                 })();
47110                 services.MyModal = MyModal;
47111             })(services = app.services || (app.services = {}));
47112         })(app || (app = {}));
47113         var app;
47114         (function (app) {
47115             var services;
47116             (function (services) {
47117                 var WebSocket = (function () {
47118                     function WebSocket($rootScope) {
47119                         this.$rootScope = $rootScope;
47120                         this.socket = io.connect();
47121                     }
47122                     WebSocket.prototype.on = function (eventName, callback) {
47123                         var socket = this.socket;
47124                         var rootScope = this.$rootScope;
47125                         socket.on(eventName, function () {
47126                             var args = arguments;
47127                             rootScope.$apply(function () {
47128                                 callback.apply(socket, args);
47129                             });
47130                         });
47131                     };
47132                     WebSocket.prototype.emit = function (eventName, data, callback) {
47133                         var socket = this.socket;
47134                         var rootScope = this.$rootScope;
47135                         this.socket.emit(eventName, data, function () {
47136                             var args = arguments;
47137                             rootScope.$apply(function () {
47138                                 if (callback)
47139                                     callback.apply(socket, args);
47140                             });
47141                         });
47142                     };
47143                     return WebSocket;
47144                 })();
47145                 services.WebSocket = WebSocket;
47146             })(services = app.services || (app.services = {}));
47147         })(app || (app = {}));
47148         var app;
47149         (function (app) {
47150             var services;
47151             (function (services) {
47152                 var Console = (function () {
47153                     function Console(WebSocket, $rootScope) {
47154                         this.WebSocket = WebSocket;
47155                         this.$rootScope = $rootScope;
47156                         this.WebSocket = WebSocket;
47157                         this.$rootScope = $rootScope;
47158                         this.directiveIDs = [];
47159                         var directiveIDs = this.directiveIDs;
47160                         this.WebSocket.on('console', function (d) {
47161                             var id = d.id;
47162                             var message = d.message;
47163                             if (directiveIDs.indexOf(id) > -1) {
47164                                 $rootScope.$emit(id, message);
47165                             }
47166                         });
47167                     }
47168                     Console.prototype.addDirective = function (id) {
47169                         if (!(this.directiveIDs.indexOf(id) > -1)) {
47170                             this.directiveIDs.push(id);
47171                         }
47172                     };
47173                     Console.prototype.removeDirective = function (id) {
47174                         var i = this.directiveIDs.indexOf(id);
47175                         if (i > -1) {
47176                             this.directiveIDs.splice(i, 1);
47177                         }
47178                     };
47179                     Console.prototype.showIDs = function () {
47180                         console.log(this.directiveIDs);
47181                     };
47182                     return Console;
47183                 })();
47184                 services.Console = Console;
47185             })(services = app.services || (app.services = {}));
47186         })(app || (app = {}));
47187         var app;
47188         (function (app) {
47189             var directives;
47190             (function (directives) {
47191                 var Command = (function () {
47192                     function Command() {
47193                         this.restrict = 'E';
47194                         this.replace = true;
47195                         this.scope = true;
47196                         this.controller = 'commandController';
47197                         this.controllerAs = 'ctrl';
47198                         this.bindToController = {
47199                             index: '=',
47200                             name: '=',
47201                             remove: '&',
47202                             list: '='
47203                         };
47204                         this.templateUrl = 'templates/command.html';
47205                     }
47206                     Command.Factory = function () {
47207                         var directive = function () {
47208                             return new Command();
47209                         };
47210                         directive.$inject = [];
47211                         return directive;
47212                     };
47213                     return Command;
47214                 })();
47215                 directives.Command = Command;
47216                 var CommandController = (function () {
47217                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
47218                         this.APIEndPoint = APIEndPoint;
47219                         this.$scope = $scope;
47220                         this.MyModal = MyModal;
47221                         this.WebSocket = WebSocket;
47222                         this.$window = $window;
47223                         this.$rootScope = $rootScope;
47224                         this.Console = Console;
47225                         var controller = this;
47226                         this.APIEndPoint
47227                             .getOptionControlFile(this.name)
47228                             .$promise
47229                             .then(function (result) {
47230                             controller.options = result.info;
47231                         });
47232                         this.APIEndPoint
47233                             .getDirectories()
47234                             .$promise
47235                             .then(function (result) {
47236                             controller.dirs = result.info;
47237                         });
47238                         this.heading = "[" + this.index + "]: dcdFilePrint";
47239                         this.isOpen = true;
47240                         this.$scope.$on('close', function () {
47241                             controller.isOpen = false;
47242                         });
47243                         function guid() {
47244                             function s4() {
47245                                 return Math.floor((1 + Math.random()) * 0x10000)
47246                                     .toString(16)
47247                                     .substring(1);
47248                             }
47249                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
47250                                 s4() + '-' + s4() + s4() + s4();
47251                         }
47252                         this.uuid = guid();
47253                         this.Console.addDirective(this.uuid);
47254                         this.Console.showIDs();
47255                     }
47256                     CommandController.prototype.submit = function () {
47257                         var opt = [];
47258                         angular.forEach(this.options, function (option) {
47259                             var obj = {
47260                                 name: option.option,
47261                                 arguments: []
47262                             };
47263                             angular.forEach(option.arg, function (arg) {
47264                                 if (arg.input) {
47265                                     if (typeof arg.input === 'object') {
47266                                         obj.arguments.push(arg.input.name);
47267                                     }
47268                                     else {
47269                                         obj.arguments.push(arg.input);
47270                                     }
47271                                 }
47272                             });
47273                             if (obj.arguments.length > 0) {
47274                                 opt.push(obj);
47275                             }
47276                         });
47277                         var execObj = {
47278                             command: this.name,
47279                             workspace: this.workspace.fileId,
47280                             options: opt
47281                         };
47282                         this.APIEndPoint
47283                             .execute(JSON.stringify(execObj))
47284                             .then(function (result) {
47285                             console.log(result);
47286                         });
47287                     };
47288                     CommandController.prototype.removeMySelf = function (index) {
47289                         this.$scope.$destroy();
47290                         this.Console.removeDirective(this.uuid);
47291                         this.remove()(index, this.list);
47292                         this.Console.showIDs();
47293                     };
47294                     CommandController.prototype.reloadFiles = function () {
47295                         var _this = this;
47296                         var fileId = this.workspace.fileId;
47297                         this.APIEndPoint
47298                             .getFiles(fileId)
47299                             .$promise
47300                             .then(function (result) {
47301                             var status = result.status;
47302                             if (status === 'success') {
47303                                 _this.files = result.info;
47304                             }
47305                             else {
47306                                 console.log(result.message);
47307                             }
47308                         });
47309                     };
47310                     CommandController.prototype.debug = function () {
47311                         var div = angular.element(this.$window.document).find("div");
47312                         var consoleTag;
47313                         var parametersTag;
47314                         angular.forEach(div, function (v) {
47315                             if (v.className === "panel-body console") {
47316                                 consoleTag = v;
47317                             }
47318                             else if (v.className === "row parameters-console") {
47319                                 parametersTag = v;
47320                             }
47321                         });
47322                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
47323                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
47324                         consoleTag.style.height = consoleHeight;
47325                         consoleTag.style.width = consoleWidth;
47326                     };
47327                     CommandController.prototype.help = function () {
47328                         this.APIEndPoint
47329                             .help(this.name)
47330                             .then(function (result) {
47331                             console.log(result);
47332                         });
47333                     };
47334                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
47335                     return CommandController;
47336                 })();
47337                 directives.CommandController = CommandController;
47338             })(directives = app.directives || (app.directives = {}));
47339         })(app || (app = {}));
47340         var app;
47341         (function (app) {
47342             var directives;
47343             (function (directives) {
47344                 var HeaderMenu = (function () {
47345                     function HeaderMenu() {
47346                         this.restrict = 'E';
47347                         this.replace = true;
47348                         this.templateUrl = 'templates/header-menu.html';
47349                         this.controller = 'HeaderMenuController';
47350                         this.controllerAs = 'hmc';
47351                         this.scope = true;
47352                     }
47353                     HeaderMenu.Factory = function () {
47354                         var directive = function () {
47355                             return new HeaderMenu();
47356                         };
47357                         return directive;
47358                     };
47359                     return HeaderMenu;
47360                 })();
47361                 directives.HeaderMenu = HeaderMenu;
47362                 var HeaderMenuController = (function () {
47363                     function HeaderMenuController($state) {
47364                         this.$state = $state;
47365                         this.isExecution = this.$state.current.name === 'execution';
47366                         this.isWorkspace = this.$state.current.name === 'workspace';
47367                         this.isHistory = this.$state.current.name === 'history';
47368                     }
47369                     HeaderMenuController.prototype.transit = function (state) {
47370                         this.$state.go(state);
47371                     };
47372                     HeaderMenuController.$inject = ['$state'];
47373                     return HeaderMenuController;
47374                 })();
47375                 directives.HeaderMenuController = HeaderMenuController;
47376             })(directives = app.directives || (app.directives = {}));
47377         })(app || (app = {}));
47378         var app;
47379         (function (app) {
47380             var directives;
47381             (function (directives) {
47382                 var Option = (function () {
47383                     function Option() {
47384                         this.restrict = 'E';
47385                         this.replace = true;
47386                         this.controller = 'optionController';
47387                         this.bindToController = {
47388                             info: '=',
47389                             files: '='
47390                         };
47391                         this.scope = true;
47392                         this.templateUrl = 'templates/option.html';
47393                         this.controllerAs = 'ctrl';
47394                     }
47395                     Option.Factory = function () {
47396                         var directive = function () {
47397                             return new Option();
47398                         };
47399                         directive.$inject = [];
47400                         return directive;
47401                     };
47402                     return Option;
47403                 })();
47404                 directives.Option = Option;
47405                 var OptionController = (function () {
47406                     function OptionController() {
47407                         var controller = this;
47408                         angular.forEach(controller.info.arg, function (arg) {
47409                             if (arg.initialValue) {
47410                                 if (arg.formType === 'number') {
47411                                     arg.input = parseInt(arg.initialValue);
47412                                 }
47413                                 else {
47414                                     arg.input = arg.initialValue;
47415                                 }
47416                             }
47417                         });
47418                     }
47419                     OptionController.$inject = [];
47420                     return OptionController;
47421                 })();
47422                 directives.OptionController = OptionController;
47423             })(directives = app.directives || (app.directives = {}));
47424         })(app || (app = {}));
47425         var app;
47426         (function (app) {
47427             var directives;
47428             (function (directives) {
47429                 var Directory = (function () {
47430                     function Directory() {
47431                         this.restrict = 'E';
47432                         this.replace = true;
47433                         this.controller = 'directoryController';
47434                         this.controllerAs = 'ctrl';
47435                         this.bindToController = {
47436                             info: '=',
47437                             add: '&',
47438                             list: '=',
47439                             files: '='
47440                         };
47441                         this.templateUrl = 'templates/directory.html';
47442                     }
47443                     Directory.Factory = function () {
47444                         var directive = function () {
47445                             return new Directory();
47446                         };
47447                         return directive;
47448                     };
47449                     return Directory;
47450                 })();
47451                 directives.Directory = Directory;
47452                 var DirectoryController = (function () {
47453                     function DirectoryController(APIEndPoint, $scope) {
47454                         this.APIEndPoint = APIEndPoint;
47455                         this.$scope = $scope;
47456                         var controller = this;
47457                         this.APIEndPoint
47458                             .getFiles(this.info.fileId)
47459                             .$promise
47460                             .then(function (result) {
47461                             if (result.status === 'success') {
47462                                 controller.files = result.info;
47463                                 angular.forEach(result.info, function (file) {
47464                                     if (file.fileType === '0') {
47465                                         var o = file;
47466                                         if (controller.info.path === '/') {
47467                                             o.path = '/' + file.name;
47468                                         }
47469                                         else {
47470                                             o.path = controller.info.path + '/' + file.name;
47471                                         }
47472                                         controller.add()(o, controller.list);
47473                                     }
47474                                 });
47475                             }
47476                             ;
47477                         });
47478                     }
47479                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
47480                     return DirectoryController;
47481                 })();
47482                 directives.DirectoryController = DirectoryController;
47483             })(directives = app.directives || (app.directives = {}));
47484         })(app || (app = {}));
47485         var app;
47486         (function (app) {
47487 <<<<<<< HEAD
47488             var directives;
47489             (function (directives) {
47490                 var Upload = (function () {
47491                     function Upload() {
47492                         this.restrict = 'E';
47493                         this.replace = true;
47494                         this.scope = true;
47495                         this.controller = 'UploadController';
47496                         this.controllerAs = 'ctrl';
47497                         this.bindToController = {
47498                             index: '=',
47499                             name: '=',
47500                             remove: '&',
47501                             list: '='
47502                         };
47503                         this.templateUrl = 'templates/upload.html';
47504                         console.log("templates/upload.html-constructor");
47505                     }
47506                     Upload.Factory = function () {
47507                         var directive = function () {
47508                             return new Upload();
47509                         };
47510                         directive.$inject = [];
47511                         return directive;
47512                     };
47513                     return Upload;
47514                 })();
47515                 directives.Upload = Upload;
47516                 var UploadController = (function () {
47517                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
47518                         this.APIEndPoint = APIEndPoint;
47519                         this.$scope = $scope;
47520                         this.MyModal = MyModal;
47521                         this.WebSocket = WebSocket;
47522                         this.$window = $window;
47523                         this.$rootScope = $rootScope;
47524                         this.Console = Console;
47525                         var controller = this;
47526                         console.log("directive.upload-constructor");
47527                     }
47528                     UploadController.prototype.submit = function () {
47529                         console.log("submit: function not supported¥n");
47530                     };
47531                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
47532                     return UploadController;
47533                 })();
47534                 directives.UploadController = UploadController;
47535             })(directives = app.directives || (app.directives = {}));
47536         })(app || (app = {}));
47537         var app;
47538         (function (app) {
47539 =======
47540 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47541             var controllers;
47542             (function (controllers) {
47543                 var Execution = (function () {
47544                     function Execution(MyModal, $scope) {
47545                         this.MyModal = MyModal;
47546                         this.$scope = $scope;
47547                         this.commandInfoList = [];
47548                     }
47549                     ;
47550                     Execution.prototype.add = function () {
47551                         this.$scope.$broadcast('close');
47552                         var commandInfoList = this.commandInfoList;
47553                         var commandInstance = this.MyModal.selectCommand();
47554                         commandInstance
47555                             .result
47556                             .then(function (command) {
47557                             commandInfoList.push(new app.declares.CommandInfo(command));
47558                         });
47559                     };
47560                     Execution.prototype.open = function () {
47561                         var result = this.MyModal.open('SelectCommand');
47562                         console.log(result);
47563                     };
47564                     Execution.prototype.remove = function (index, list) {
47565                         list.splice(index, 1);
47566                     };
47567                     Execution.prototype.close = function () {
47568                         console.log("close");
47569                     };
47570                     Execution.$inject = ['MyModal', '$scope'];
47571                     return Execution;
47572                 })();
47573                 controllers.Execution = Execution;
47574             })(controllers = app.controllers || (app.controllers = {}));
47575         })(app || (app = {}));
47576         var app;
47577         (function (app) {
47578             var controllers;
47579             (function (controllers) {
47580                 var Workspace = (function () {
47581                     function Workspace($scope, APIEndPoint, MyModal) {
47582                         this.$scope = $scope;
47583                         this.APIEndPoint = APIEndPoint;
47584                         this.MyModal = MyModal;
47585                         this.directoryList = [];
47586                         var controller = this;
47587                         var directoryList = this.directoryList;
47588                         var o = {
47589                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
47590                             name: '',
47591                             parentId: '',
47592                             fileType: '',
47593                             createdAt: '',
47594                             updatedAt: '',
47595                             path: '/'
47596                         };
47597                         directoryList.push(o);
47598                     }
47599                     Workspace.prototype.addDirectory = function (info, directoryList) {
47600                         directoryList.push(info);
47601                     };
47602 <<<<<<< HEAD
47603                     Workspace.prototype.upload = function () {
47604                         this.MyModal.upload();
47605                     };
47606 =======
47607 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47608                     Workspace.prototype.debug = function () {
47609                         this.MyModal.preview();
47610                     };
47611                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
47612                     return Workspace;
47613                 })();
47614                 controllers.Workspace = Workspace;
47615             })(controllers = app.controllers || (app.controllers = {}));
47616         })(app || (app = {}));
47617         var app;
47618         (function (app) {
47619             var controllers;
47620             (function (controllers) {
47621                 var History = (function () {
47622                     function History($scope) {
47623                         this.page = "History";
47624                     }
47625                     History.$inject = ['$scope'];
47626                     return History;
47627                 })();
47628                 controllers.History = History;
47629             })(controllers = app.controllers || (app.controllers = {}));
47630         })(app || (app = {}));
47631         var app;
47632         (function (app) {
47633             var controllers;
47634             (function (controllers) {
47635                 var SelectCommand = (function () {
47636                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
47637                         this.APIEndPoint = APIEndPoint;
47638                         this.$modalInstance = $modalInstance;
47639                         var controller = this;
47640                         this.APIEndPoint
47641                             .getTags()
47642                             .$promise.then(function (result) {
47643                             controller.tags = result.info;
47644                         });
47645                         this.APIEndPoint
47646                             .getCommands()
47647                             .$promise.then(function (result) {
47648                             controller.commands = result.info;
47649                         });
47650                         this.currentTag = 'all';
47651                     }
47652                     SelectCommand.prototype.changeTag = function (tag) {
47653                         this.currentTag = tag;
47654                     };
47655                     SelectCommand.prototype.selectCommand = function (command) {
47656                         this.$modalInstance.close(command);
47657                     };
47658                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
47659                     return SelectCommand;
47660                 })();
47661                 controllers.SelectCommand = SelectCommand;
47662             })(controllers = app.controllers || (app.controllers = {}));
47663         })(app || (app = {}));
47664         var app;
47665         (function (app) {
47666             var controllers;
47667             (function (controllers) {
47668 <<<<<<< HEAD
47669                 var Upload = (function () {
47670                     function Upload($scope, APIEndPoint, $modalInstance) {
47671                         this.APIEndPoint = APIEndPoint;
47672                         this.$modalInstance = $modalInstance;
47673                         var controller = this;
47674                         console.log('controller.upload-controllers');
47675                     }
47676                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
47677                     return Upload;
47678                 })();
47679                 controllers.Upload = Upload;
47680             })(controllers = app.controllers || (app.controllers = {}));
47681         })(app || (app = {}));
47682         var app;
47683         (function (app) {
47684             var controllers;
47685             (function (controllers) {
47686 =======
47687 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47688                 var Preview = (function () {
47689                     function Preview($scope, APIEndPoint, $modalInstance) {
47690                         this.APIEndPoint = APIEndPoint;
47691                         this.$modalInstance = $modalInstance;
47692                         var controller = this;
47693                         console.log('preview');
47694                     }
47695                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
47696                     return Preview;
47697                 })();
47698                 controllers.Preview = Preview;
47699             })(controllers = app.controllers || (app.controllers = {}));
47700         })(app || (app = {}));
47701         var filters;
47702         (function (filters) {
47703             function Tag() {
47704                 return function (commands, tag) {
47705                     var result = [];
47706                     angular.forEach(commands, function (command) {
47707                         var flag = false;
47708                         angular.forEach(command.tags, function (value) {
47709                             if (tag === value)
47710                                 flag = true;
47711                         });
47712                         if (flag)
47713                             result.push(command);
47714                     });
47715                     return result;
47716                 };
47717             }
47718             filters.Tag = Tag;
47719         })(filters || (filters = {}));
47720         var app;
47721         (function (app) {
47722             'use strict';
47723             var appName = 'zephyr';
47724             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
47725             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
47726                 $urlRouterProvider.otherwise('/execution');
47727                 $locationProvider.html5Mode({
47728                     enabled: true,
47729                     requireBase: false
47730                 });
47731                 $stateProvider
47732                     .state('execution', {
47733                     url: '/execution',
47734                     templateUrl: 'templates/execution.html',
47735                     controller: 'executionController',
47736                     controllerAs: 'c'
47737                 })
47738                     .state('workspace', {
47739                     url: '/workspace',
47740                     templateUrl: 'templates/workspace.html',
47741                     controller: 'workspaceController',
47742                     controllerAs: 'c'
47743                 })
47744                     .state('history', {
47745                     url: '/history',
47746                     templateUrl: 'templates/history.html',
47747                     controller: 'historyController',
47748                     controllerAs: 'c'
47749                 });
47750             });
47751             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
47752             app.zephyr.service('MyModal', app.services.MyModal);
47753             app.zephyr.service('WebSocket', app.services.WebSocket);
47754             app.zephyr.service('Console', app.services.Console);
47755             app.zephyr.filter('Tag', filters.Tag);
47756             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
47757             app.zephyr.controller('previewController', app.controllers.Preview);
47758 <<<<<<< HEAD
47759             app.zephyr.controller('uploadController', app.controllers.Upload);
47760 =======
47761 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47762             app.zephyr.controller('executionController', app.controllers.Execution);
47763             app.zephyr.controller('workspaceController', app.controllers.Workspace);
47764             app.zephyr.controller('historyController', app.controllers.History);
47765             app.zephyr.controller('commandController', app.directives.CommandController);
47766             app.zephyr.controller('optionController', app.directives.OptionController);
47767             app.zephyr.controller('directoryController', app.directives.DirectoryController);
47768             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
47769 <<<<<<< HEAD
47770             app.zephyr.controller('uploadController', app.directives.UploadController);
47771 =======
47772 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47773             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
47774             app.zephyr.directive('command', app.directives.Command.Factory());
47775             app.zephyr.directive('option', app.directives.Option.Factory());
47776             app.zephyr.directive('directory', app.directives.Directory.Factory());
47777         })(app || (app = {}));
47778
47779
47780 /***/ },
47781 <<<<<<< HEAD
47782 /* 11 */
47783 =======
47784 /* 9 */
47785 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47786 /***/ function(module, exports) {
47787
47788         var app;
47789         (function (app) {
47790             var declares;
47791             (function (declares) {
47792                 var CommandInfo = (function () {
47793                     function CommandInfo(name) {
47794                         this.name = name;
47795                     }
47796                     return CommandInfo;
47797                 })();
47798                 declares.CommandInfo = CommandInfo;
47799             })(declares = app.declares || (app.declares = {}));
47800         })(app || (app = {}));
47801         var app;
47802         (function (app) {
47803             var services;
47804             (function (services) {
47805                 var APIEndPoint = (function () {
47806                     function APIEndPoint($resource, $http) {
47807                         this.$resource = $resource;
47808                         this.$http = $http;
47809                     }
47810                     APIEndPoint.prototype.resource = function (endPoint, data) {
47811                         var customAction = {
47812                             method: 'GET',
47813                             isArray: false
47814                         };
47815                         var execute = {
47816                             method: 'POST',
47817                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
47818                         };
47819                         return this.$resource(endPoint, {}, { execute: execute });
47820                     };
47821                     APIEndPoint.prototype.getOptionControlFile = function (command) {
47822                         var endPoint = '/api/v1/optionControlFile/' + command;
47823                         return this.resource(endPoint, {}).get();
47824                     };
47825                     APIEndPoint.prototype.getFiles = function (fileId) {
47826                         var endPoint = '/api/v1/workspace';
47827                         if (fileId) {
47828                             endPoint += '/' + fileId;
47829                         }
47830                         return this.resource(endPoint, {}).get();
47831                     };
47832                     APIEndPoint.prototype.getDirectories = function () {
47833                         var endPoint = '/api/v1/all/workspace/directory';
47834                         return this.resource(endPoint, {}).get();
47835                     };
47836                     APIEndPoint.prototype.getTags = function () {
47837                         var endPoint = '/api/v1/tagList';
47838                         return this.resource(endPoint, {}).get();
47839                     };
47840                     APIEndPoint.prototype.getCommands = function () {
47841                         var endPoint = '/api/v1/commandList';
47842                         return this.resource(endPoint, {}).get();
47843                     };
47844                     APIEndPoint.prototype.execute = function (data) {
47845                         var endPoint = '/api/v1/execution';
47846                         var fd = new FormData();
47847                         fd.append('data', data);
47848                         return this.$http.post(endPoint, fd, {
47849                             headers: { 'Content-Type': undefined },
47850                             transformRequest: angular.identity
47851                         });
47852                     };
47853                     APIEndPoint.prototype.debug = function () {
47854                         var endPoint = '/api/v1/debug';
47855                         return this.$http.get(endPoint);
47856                     };
47857 <<<<<<< HEAD
47858                     APIEndPoint.prototype.upload = function () {
47859                         var endPoint = '/api/v1/upload';
47860                         return this.$http.get(endPoint);
47861                     };
47862 =======
47863 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47864                     APIEndPoint.prototype.help = function (command) {
47865                         var endPoint = '/api/v1/help/' + command;
47866                         return this.$http.get(endPoint);
47867                     };
47868                     return APIEndPoint;
47869                 })();
47870                 services.APIEndPoint = APIEndPoint;
47871             })(services = app.services || (app.services = {}));
47872         })(app || (app = {}));
47873         var app;
47874         (function (app) {
47875             var services;
47876             (function (services) {
47877                 var MyModal = (function () {
47878                     function MyModal($uibModal) {
47879                         this.$uibModal = $uibModal;
47880                         this.modalOption = {
47881                             backdrop: true,
47882                             controller: null,
47883                             templateUrl: null,
47884                             size: null
47885                         };
47886                     }
47887                     MyModal.prototype.open = function (modalName) {
47888                         if (modalName === 'SelectCommand') {
47889                             this.modalOption.templateUrl = 'templates/select-command.html';
47890                             this.modalOption.size = 'lg';
47891                         }
47892                         return this.$uibModal.open(this.modalOption);
47893                     };
47894                     MyModal.prototype.selectCommand = function () {
47895                         this.modalOption.templateUrl = 'templates/select-command.html';
47896                         this.modalOption.controller = 'selectCommandController';
47897                         this.modalOption.controllerAs = 'c';
47898                         this.modalOption.size = 'lg';
47899                         return this.$uibModal.open(this.modalOption);
47900                     };
47901                     MyModal.prototype.preview = function () {
47902                         this.modalOption.templateUrl = 'templates/preview.html';
47903                         this.modalOption.controller = 'previewController';
47904                         this.modalOption.controllerAs = 'c';
47905                         this.modalOption.size = 'lg';
47906                         return this.$uibModal.open(this.modalOption);
47907                     };
47908 <<<<<<< HEAD
47909                     MyModal.prototype.upload = function () {
47910                         this.modalOption.templateUrl = 'templates/upload.html';
47911                         this.modalOption.controller = 'uploadController';
47912                         this.modalOption.controllerAs = 'c';
47913                         this.modalOption.size = 'lg';
47914                         return this.$uibModal.open(this.modalOption);
47915                     };
47916 =======
47917 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
47918                     MyModal.$inject = ['$uibModal'];
47919                     return MyModal;
47920                 })();
47921                 services.MyModal = MyModal;
47922             })(services = app.services || (app.services = {}));
47923         })(app || (app = {}));
47924         var app;
47925         (function (app) {
47926             var services;
47927             (function (services) {
47928                 var WebSocket = (function () {
47929                     function WebSocket($rootScope) {
47930                         this.$rootScope = $rootScope;
47931                         this.socket = io.connect();
47932                     }
47933                     WebSocket.prototype.on = function (eventName, callback) {
47934                         var socket = this.socket;
47935                         var rootScope = this.$rootScope;
47936                         socket.on(eventName, function () {
47937                             var args = arguments;
47938                             rootScope.$apply(function () {
47939                                 callback.apply(socket, args);
47940                             });
47941                         });
47942                     };
47943                     WebSocket.prototype.emit = function (eventName, data, callback) {
47944                         var socket = this.socket;
47945                         var rootScope = this.$rootScope;
47946                         this.socket.emit(eventName, data, function () {
47947                             var args = arguments;
47948                             rootScope.$apply(function () {
47949                                 if (callback)
47950                                     callback.apply(socket, args);
47951                             });
47952                         });
47953                     };
47954                     return WebSocket;
47955                 })();
47956                 services.WebSocket = WebSocket;
47957             })(services = app.services || (app.services = {}));
47958         })(app || (app = {}));
47959         var app;
47960         (function (app) {
47961             var services;
47962             (function (services) {
47963                 var Console = (function () {
47964                     function Console(WebSocket, $rootScope) {
47965                         this.WebSocket = WebSocket;
47966                         this.$rootScope = $rootScope;
47967                         this.WebSocket = WebSocket;
47968                         this.$rootScope = $rootScope;
47969                         this.directiveIDs = [];
47970                         var directiveIDs = this.directiveIDs;
47971                         this.WebSocket.on('console', function (d) {
47972                             var id = d.id;
47973                             var message = d.message;
47974                             if (directiveIDs.indexOf(id) > -1) {
47975                                 $rootScope.$emit(id, message);
47976                             }
47977                         });
47978                     }
47979                     Console.prototype.addDirective = function (id) {
47980                         if (!(this.directiveIDs.indexOf(id) > -1)) {
47981                             this.directiveIDs.push(id);
47982                         }
47983                     };
47984                     Console.prototype.removeDirective = function (id) {
47985                         var i = this.directiveIDs.indexOf(id);
47986                         if (i > -1) {
47987                             this.directiveIDs.splice(i, 1);
47988                         }
47989                     };
47990                     Console.prototype.showIDs = function () {
47991                         console.log(this.directiveIDs);
47992                     };
47993                     return Console;
47994                 })();
47995                 services.Console = Console;
47996             })(services = app.services || (app.services = {}));
47997         })(app || (app = {}));
47998         var app;
47999         (function (app) {
48000             var directives;
48001             (function (directives) {
48002                 var Command = (function () {
48003                     function Command() {
48004                         this.restrict = 'E';
48005                         this.replace = true;
48006                         this.scope = true;
48007                         this.controller = 'commandController';
48008                         this.controllerAs = 'ctrl';
48009                         this.bindToController = {
48010                             index: '=',
48011                             name: '=',
48012                             remove: '&',
48013                             list: '='
48014                         };
48015                         this.templateUrl = 'templates/command.html';
48016                     }
48017                     Command.Factory = function () {
48018                         var directive = function () {
48019                             return new Command();
48020                         };
48021                         directive.$inject = [];
48022                         return directive;
48023                     };
48024                     return Command;
48025                 })();
48026                 directives.Command = Command;
48027                 var CommandController = (function () {
48028                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
48029                         this.APIEndPoint = APIEndPoint;
48030                         this.$scope = $scope;
48031                         this.MyModal = MyModal;
48032                         this.WebSocket = WebSocket;
48033                         this.$window = $window;
48034                         this.$rootScope = $rootScope;
48035                         this.Console = Console;
48036                         var controller = this;
48037                         this.APIEndPoint
48038                             .getOptionControlFile(this.name)
48039                             .$promise
48040                             .then(function (result) {
48041                             controller.options = result.info;
48042                         });
48043                         this.APIEndPoint
48044                             .getDirectories()
48045                             .$promise
48046                             .then(function (result) {
48047                             controller.dirs = result.info;
48048                         });
48049                         this.heading = "[" + this.index + "]: dcdFilePrint";
48050                         this.isOpen = true;
48051                         this.$scope.$on('close', function () {
48052                             controller.isOpen = false;
48053                         });
48054                         function guid() {
48055                             function s4() {
48056                                 return Math.floor((1 + Math.random()) * 0x10000)
48057                                     .toString(16)
48058                                     .substring(1);
48059                             }
48060                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
48061                                 s4() + '-' + s4() + s4() + s4();
48062                         }
48063                         this.uuid = guid();
48064                         this.Console.addDirective(this.uuid);
48065                         this.Console.showIDs();
48066                     }
48067                     CommandController.prototype.submit = function () {
48068                         var opt = [];
48069                         angular.forEach(this.options, function (option) {
48070                             var obj = {
48071                                 name: option.option,
48072                                 arguments: []
48073                             };
48074                             angular.forEach(option.arg, function (arg) {
48075                                 if (arg.input) {
48076                                     if (typeof arg.input === 'object') {
48077                                         obj.arguments.push(arg.input.name);
48078                                     }
48079                                     else {
48080                                         obj.arguments.push(arg.input);
48081                                     }
48082                                 }
48083                             });
48084                             if (obj.arguments.length > 0) {
48085                                 opt.push(obj);
48086                             }
48087                         });
48088                         var execObj = {
48089                             command: this.name,
48090                             workspace: this.workspace.fileId,
48091                             options: opt
48092                         };
48093                         this.APIEndPoint
48094                             .execute(JSON.stringify(execObj))
48095                             .then(function (result) {
48096                             console.log(result);
48097                         });
48098                     };
48099                     CommandController.prototype.removeMySelf = function (index) {
48100                         this.$scope.$destroy();
48101                         this.Console.removeDirective(this.uuid);
48102                         this.remove()(index, this.list);
48103                         this.Console.showIDs();
48104                     };
48105                     CommandController.prototype.reloadFiles = function () {
48106                         var _this = this;
48107                         var fileId = this.workspace.fileId;
48108                         this.APIEndPoint
48109                             .getFiles(fileId)
48110                             .$promise
48111                             .then(function (result) {
48112                             var status = result.status;
48113                             if (status === 'success') {
48114                                 _this.files = result.info;
48115                             }
48116                             else {
48117                                 console.log(result.message);
48118                             }
48119                         });
48120                     };
48121                     CommandController.prototype.debug = function () {
48122                         var div = angular.element(this.$window.document).find("div");
48123                         var consoleTag;
48124                         var parametersTag;
48125                         angular.forEach(div, function (v) {
48126                             if (v.className === "panel-body console") {
48127                                 consoleTag = v;
48128                             }
48129                             else if (v.className === "row parameters-console") {
48130                                 parametersTag = v;
48131                             }
48132                         });
48133                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
48134                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
48135                         consoleTag.style.height = consoleHeight;
48136                         consoleTag.style.width = consoleWidth;
48137                     };
48138                     CommandController.prototype.help = function () {
48139                         this.APIEndPoint
48140                             .help(this.name)
48141                             .then(function (result) {
48142                             console.log(result);
48143                         });
48144                     };
48145                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
48146                     return CommandController;
48147                 })();
48148                 directives.CommandController = CommandController;
48149             })(directives = app.directives || (app.directives = {}));
48150         })(app || (app = {}));
48151         var app;
48152         (function (app) {
48153             var directives;
48154             (function (directives) {
48155                 var HeaderMenu = (function () {
48156                     function HeaderMenu() {
48157                         this.restrict = 'E';
48158                         this.replace = true;
48159                         this.templateUrl = 'templates/header-menu.html';
48160                         this.controller = 'HeaderMenuController';
48161                         this.controllerAs = 'hmc';
48162                         this.scope = true;
48163                     }
48164                     HeaderMenu.Factory = function () {
48165                         var directive = function () {
48166                             return new HeaderMenu();
48167                         };
48168                         return directive;
48169                     };
48170                     return HeaderMenu;
48171                 })();
48172                 directives.HeaderMenu = HeaderMenu;
48173                 var HeaderMenuController = (function () {
48174                     function HeaderMenuController($state) {
48175                         this.$state = $state;
48176                         this.isExecution = this.$state.current.name === 'execution';
48177                         this.isWorkspace = this.$state.current.name === 'workspace';
48178                         this.isHistory = this.$state.current.name === 'history';
48179                     }
48180                     HeaderMenuController.prototype.transit = function (state) {
48181                         this.$state.go(state);
48182                     };
48183                     HeaderMenuController.$inject = ['$state'];
48184                     return HeaderMenuController;
48185                 })();
48186                 directives.HeaderMenuController = HeaderMenuController;
48187             })(directives = app.directives || (app.directives = {}));
48188         })(app || (app = {}));
48189         var app;
48190         (function (app) {
48191             var directives;
48192             (function (directives) {
48193                 var Option = (function () {
48194                     function Option() {
48195                         this.restrict = 'E';
48196                         this.replace = true;
48197                         this.controller = 'optionController';
48198                         this.bindToController = {
48199                             info: '=',
48200                             files: '='
48201                         };
48202                         this.scope = true;
48203                         this.templateUrl = 'templates/option.html';
48204                         this.controllerAs = 'ctrl';
48205                     }
48206                     Option.Factory = function () {
48207                         var directive = function () {
48208                             return new Option();
48209                         };
48210                         directive.$inject = [];
48211                         return directive;
48212                     };
48213                     return Option;
48214                 })();
48215                 directives.Option = Option;
48216                 var OptionController = (function () {
48217                     function OptionController() {
48218                         var controller = this;
48219                         angular.forEach(controller.info.arg, function (arg) {
48220                             if (arg.initialValue) {
48221                                 if (arg.formType === 'number') {
48222                                     arg.input = parseInt(arg.initialValue);
48223                                 }
48224                                 else {
48225                                     arg.input = arg.initialValue;
48226                                 }
48227                             }
48228                         });
48229                     }
48230                     OptionController.$inject = [];
48231                     return OptionController;
48232                 })();
48233                 directives.OptionController = OptionController;
48234             })(directives = app.directives || (app.directives = {}));
48235         })(app || (app = {}));
48236         var app;
48237         (function (app) {
48238             var directives;
48239             (function (directives) {
48240                 var Directory = (function () {
48241                     function Directory() {
48242                         this.restrict = 'E';
48243                         this.replace = true;
48244                         this.controller = 'directoryController';
48245                         this.controllerAs = 'ctrl';
48246                         this.bindToController = {
48247                             info: '=',
48248                             add: '&',
48249                             list: '=',
48250                             files: '='
48251                         };
48252                         this.templateUrl = 'templates/directory.html';
48253                     }
48254                     Directory.Factory = function () {
48255                         var directive = function () {
48256                             return new Directory();
48257                         };
48258                         return directive;
48259                     };
48260                     return Directory;
48261                 })();
48262                 directives.Directory = Directory;
48263                 var DirectoryController = (function () {
48264                     function DirectoryController(APIEndPoint, $scope) {
48265                         this.APIEndPoint = APIEndPoint;
48266                         this.$scope = $scope;
48267                         var controller = this;
48268                         this.APIEndPoint
48269                             .getFiles(this.info.fileId)
48270                             .$promise
48271                             .then(function (result) {
48272                             if (result.status === 'success') {
48273                                 controller.files = result.info;
48274                                 angular.forEach(result.info, function (file) {
48275                                     if (file.fileType === '0') {
48276                                         var o = file;
48277                                         if (controller.info.path === '/') {
48278                                             o.path = '/' + file.name;
48279                                         }
48280                                         else {
48281                                             o.path = controller.info.path + '/' + file.name;
48282                                         }
48283                                         controller.add()(o, controller.list);
48284                                     }
48285                                 });
48286                             }
48287                             ;
48288                         });
48289                     }
48290                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
48291                     return DirectoryController;
48292                 })();
48293                 directives.DirectoryController = DirectoryController;
48294             })(directives = app.directives || (app.directives = {}));
48295         })(app || (app = {}));
48296         var app;
48297         (function (app) {
48298 <<<<<<< HEAD
48299             var directives;
48300             (function (directives) {
48301                 var Upload = (function () {
48302                     function Upload() {
48303                         this.restrict = 'E';
48304                         this.replace = true;
48305                         this.scope = true;
48306                         this.controller = 'UploadController';
48307                         this.controllerAs = 'ctrl';
48308                         this.bindToController = {
48309                             index: '=',
48310                             name: '=',
48311                             remove: '&',
48312                             list: '='
48313                         };
48314                         this.templateUrl = 'templates/upload.html';
48315                         console.log("templates/upload.html-constructor");
48316                     }
48317                     Upload.Factory = function () {
48318                         var directive = function () {
48319                             return new Upload();
48320                         };
48321                         directive.$inject = [];
48322                         return directive;
48323                     };
48324                     return Upload;
48325                 })();
48326                 directives.Upload = Upload;
48327                 var UploadController = (function () {
48328                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
48329                         this.APIEndPoint = APIEndPoint;
48330                         this.$scope = $scope;
48331                         this.MyModal = MyModal;
48332                         this.WebSocket = WebSocket;
48333                         this.$window = $window;
48334                         this.$rootScope = $rootScope;
48335                         this.Console = Console;
48336                         var controller = this;
48337                         console.log("directive.upload-constructor");
48338                     }
48339                     UploadController.prototype.submit = function () {
48340                         console.log("submit: function not supported¥n");
48341                     };
48342                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
48343                     return UploadController;
48344                 })();
48345                 directives.UploadController = UploadController;
48346             })(directives = app.directives || (app.directives = {}));
48347         })(app || (app = {}));
48348         var app;
48349         (function (app) {
48350 =======
48351 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48352             var controllers;
48353             (function (controllers) {
48354                 var Execution = (function () {
48355                     function Execution(MyModal, $scope) {
48356                         this.MyModal = MyModal;
48357                         this.$scope = $scope;
48358                         this.commandInfoList = [];
48359                     }
48360                     ;
48361                     Execution.prototype.add = function () {
48362                         this.$scope.$broadcast('close');
48363                         var commandInfoList = this.commandInfoList;
48364                         var commandInstance = this.MyModal.selectCommand();
48365                         commandInstance
48366                             .result
48367                             .then(function (command) {
48368                             commandInfoList.push(new app.declares.CommandInfo(command));
48369                         });
48370                     };
48371                     Execution.prototype.open = function () {
48372                         var result = this.MyModal.open('SelectCommand');
48373                         console.log(result);
48374                     };
48375                     Execution.prototype.remove = function (index, list) {
48376                         list.splice(index, 1);
48377                     };
48378                     Execution.prototype.close = function () {
48379                         console.log("close");
48380                     };
48381                     Execution.$inject = ['MyModal', '$scope'];
48382                     return Execution;
48383                 })();
48384                 controllers.Execution = Execution;
48385             })(controllers = app.controllers || (app.controllers = {}));
48386         })(app || (app = {}));
48387         var app;
48388         (function (app) {
48389             var controllers;
48390             (function (controllers) {
48391                 var Workspace = (function () {
48392                     function Workspace($scope, APIEndPoint, MyModal) {
48393                         this.$scope = $scope;
48394                         this.APIEndPoint = APIEndPoint;
48395                         this.MyModal = MyModal;
48396                         this.directoryList = [];
48397                         var controller = this;
48398                         var directoryList = this.directoryList;
48399                         var o = {
48400                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
48401                             name: '',
48402                             parentId: '',
48403                             fileType: '',
48404                             createdAt: '',
48405                             updatedAt: '',
48406                             path: '/'
48407                         };
48408                         directoryList.push(o);
48409                     }
48410                     Workspace.prototype.addDirectory = function (info, directoryList) {
48411                         directoryList.push(info);
48412                     };
48413 <<<<<<< HEAD
48414                     Workspace.prototype.upload = function () {
48415                         this.MyModal.upload();
48416                     };
48417 =======
48418 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48419                     Workspace.prototype.debug = function () {
48420                         this.MyModal.preview();
48421                     };
48422                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
48423                     return Workspace;
48424                 })();
48425                 controllers.Workspace = Workspace;
48426             })(controllers = app.controllers || (app.controllers = {}));
48427         })(app || (app = {}));
48428         var app;
48429         (function (app) {
48430             var controllers;
48431             (function (controllers) {
48432                 var History = (function () {
48433                     function History($scope) {
48434                         this.page = "History";
48435                     }
48436                     History.$inject = ['$scope'];
48437                     return History;
48438                 })();
48439                 controllers.History = History;
48440             })(controllers = app.controllers || (app.controllers = {}));
48441         })(app || (app = {}));
48442         var app;
48443         (function (app) {
48444             var controllers;
48445             (function (controllers) {
48446                 var SelectCommand = (function () {
48447                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
48448                         this.APIEndPoint = APIEndPoint;
48449                         this.$modalInstance = $modalInstance;
48450                         var controller = this;
48451                         this.APIEndPoint
48452                             .getTags()
48453                             .$promise.then(function (result) {
48454                             controller.tags = result.info;
48455                         });
48456                         this.APIEndPoint
48457                             .getCommands()
48458                             .$promise.then(function (result) {
48459                             controller.commands = result.info;
48460                         });
48461                         this.currentTag = 'all';
48462                     }
48463                     SelectCommand.prototype.changeTag = function (tag) {
48464                         this.currentTag = tag;
48465                     };
48466                     SelectCommand.prototype.selectCommand = function (command) {
48467                         this.$modalInstance.close(command);
48468                     };
48469                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
48470                     return SelectCommand;
48471                 })();
48472                 controllers.SelectCommand = SelectCommand;
48473             })(controllers = app.controllers || (app.controllers = {}));
48474         })(app || (app = {}));
48475         var app;
48476         (function (app) {
48477             var controllers;
48478             (function (controllers) {
48479 <<<<<<< HEAD
48480                 var Upload = (function () {
48481                     function Upload($scope, APIEndPoint, $modalInstance) {
48482                         this.APIEndPoint = APIEndPoint;
48483                         this.$modalInstance = $modalInstance;
48484                         var controller = this;
48485                         console.log('controller.upload-controllers');
48486                     }
48487                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
48488                     return Upload;
48489                 })();
48490                 controllers.Upload = Upload;
48491             })(controllers = app.controllers || (app.controllers = {}));
48492         })(app || (app = {}));
48493         var app;
48494         (function (app) {
48495             var controllers;
48496             (function (controllers) {
48497 =======
48498 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48499                 var Preview = (function () {
48500                     function Preview($scope, APIEndPoint, $modalInstance) {
48501                         this.APIEndPoint = APIEndPoint;
48502                         this.$modalInstance = $modalInstance;
48503                         var controller = this;
48504                         console.log('preview');
48505                     }
48506                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
48507                     return Preview;
48508                 })();
48509                 controllers.Preview = Preview;
48510             })(controllers = app.controllers || (app.controllers = {}));
48511         })(app || (app = {}));
48512         var filters;
48513         (function (filters) {
48514             function Tag() {
48515                 return function (commands, tag) {
48516                     var result = [];
48517                     angular.forEach(commands, function (command) {
48518                         var flag = false;
48519                         angular.forEach(command.tags, function (value) {
48520                             if (tag === value)
48521                                 flag = true;
48522                         });
48523                         if (flag)
48524                             result.push(command);
48525                     });
48526                     return result;
48527                 };
48528             }
48529             filters.Tag = Tag;
48530         })(filters || (filters = {}));
48531         var app;
48532         (function (app) {
48533             'use strict';
48534             var appName = 'zephyr';
48535             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
48536             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
48537                 $urlRouterProvider.otherwise('/execution');
48538                 $locationProvider.html5Mode({
48539                     enabled: true,
48540                     requireBase: false
48541                 });
48542                 $stateProvider
48543                     .state('execution', {
48544                     url: '/execution',
48545                     templateUrl: 'templates/execution.html',
48546                     controller: 'executionController',
48547                     controllerAs: 'c'
48548                 })
48549                     .state('workspace', {
48550                     url: '/workspace',
48551                     templateUrl: 'templates/workspace.html',
48552                     controller: 'workspaceController',
48553                     controllerAs: 'c'
48554                 })
48555                     .state('history', {
48556                     url: '/history',
48557                     templateUrl: 'templates/history.html',
48558                     controller: 'historyController',
48559                     controllerAs: 'c'
48560                 });
48561             });
48562             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
48563             app.zephyr.service('MyModal', app.services.MyModal);
48564             app.zephyr.service('WebSocket', app.services.WebSocket);
48565             app.zephyr.service('Console', app.services.Console);
48566             app.zephyr.filter('Tag', filters.Tag);
48567             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
48568             app.zephyr.controller('previewController', app.controllers.Preview);
48569 <<<<<<< HEAD
48570             app.zephyr.controller('uploadController', app.controllers.Upload);
48571 =======
48572 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48573             app.zephyr.controller('executionController', app.controllers.Execution);
48574             app.zephyr.controller('workspaceController', app.controllers.Workspace);
48575             app.zephyr.controller('historyController', app.controllers.History);
48576             app.zephyr.controller('commandController', app.directives.CommandController);
48577             app.zephyr.controller('optionController', app.directives.OptionController);
48578             app.zephyr.controller('directoryController', app.directives.DirectoryController);
48579             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
48580 <<<<<<< HEAD
48581             app.zephyr.controller('uploadController', app.directives.UploadController);
48582 =======
48583 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48584             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
48585             app.zephyr.directive('command', app.directives.Command.Factory());
48586             app.zephyr.directive('option', app.directives.Option.Factory());
48587             app.zephyr.directive('directory', app.directives.Directory.Factory());
48588         })(app || (app = {}));
48589
48590
48591 /***/ },
48592 <<<<<<< HEAD
48593 /* 12 */
48594 =======
48595 /* 10 */
48596 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48597 /***/ function(module, exports) {
48598
48599         var app;
48600         (function (app) {
48601             var declares;
48602             (function (declares) {
48603                 var CommandInfo = (function () {
48604                     function CommandInfo(name) {
48605                         this.name = name;
48606                     }
48607                     return CommandInfo;
48608                 })();
48609                 declares.CommandInfo = CommandInfo;
48610             })(declares = app.declares || (app.declares = {}));
48611         })(app || (app = {}));
48612         var app;
48613         (function (app) {
48614             var services;
48615             (function (services) {
48616                 var APIEndPoint = (function () {
48617                     function APIEndPoint($resource, $http) {
48618                         this.$resource = $resource;
48619                         this.$http = $http;
48620                     }
48621                     APIEndPoint.prototype.resource = function (endPoint, data) {
48622                         var customAction = {
48623                             method: 'GET',
48624                             isArray: false
48625                         };
48626                         var execute = {
48627                             method: 'POST',
48628                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
48629                         };
48630                         return this.$resource(endPoint, {}, { execute: execute });
48631                     };
48632                     APIEndPoint.prototype.getOptionControlFile = function (command) {
48633                         var endPoint = '/api/v1/optionControlFile/' + command;
48634                         return this.resource(endPoint, {}).get();
48635                     };
48636                     APIEndPoint.prototype.getFiles = function (fileId) {
48637                         var endPoint = '/api/v1/workspace';
48638                         if (fileId) {
48639                             endPoint += '/' + fileId;
48640                         }
48641                         return this.resource(endPoint, {}).get();
48642                     };
48643                     APIEndPoint.prototype.getDirectories = function () {
48644                         var endPoint = '/api/v1/all/workspace/directory';
48645                         return this.resource(endPoint, {}).get();
48646                     };
48647                     APIEndPoint.prototype.getTags = function () {
48648                         var endPoint = '/api/v1/tagList';
48649                         return this.resource(endPoint, {}).get();
48650                     };
48651                     APIEndPoint.prototype.getCommands = function () {
48652                         var endPoint = '/api/v1/commandList';
48653                         return this.resource(endPoint, {}).get();
48654                     };
48655                     APIEndPoint.prototype.execute = function (data) {
48656                         var endPoint = '/api/v1/execution';
48657                         var fd = new FormData();
48658                         fd.append('data', data);
48659                         return this.$http.post(endPoint, fd, {
48660                             headers: { 'Content-Type': undefined },
48661                             transformRequest: angular.identity
48662                         });
48663                     };
48664                     APIEndPoint.prototype.debug = function () {
48665                         var endPoint = '/api/v1/debug';
48666                         return this.$http.get(endPoint);
48667                     };
48668 <<<<<<< HEAD
48669                     APIEndPoint.prototype.upload = function () {
48670                         var endPoint = '/api/v1/upload';
48671                         return this.$http.get(endPoint);
48672                     };
48673 =======
48674 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48675                     APIEndPoint.prototype.help = function (command) {
48676                         var endPoint = '/api/v1/help/' + command;
48677                         return this.$http.get(endPoint);
48678                     };
48679                     return APIEndPoint;
48680                 })();
48681                 services.APIEndPoint = APIEndPoint;
48682             })(services = app.services || (app.services = {}));
48683         })(app || (app = {}));
48684         var app;
48685         (function (app) {
48686             var services;
48687             (function (services) {
48688                 var MyModal = (function () {
48689                     function MyModal($uibModal) {
48690                         this.$uibModal = $uibModal;
48691                         this.modalOption = {
48692                             backdrop: true,
48693                             controller: null,
48694                             templateUrl: null,
48695                             size: null
48696                         };
48697                     }
48698                     MyModal.prototype.open = function (modalName) {
48699                         if (modalName === 'SelectCommand') {
48700                             this.modalOption.templateUrl = 'templates/select-command.html';
48701                             this.modalOption.size = 'lg';
48702                         }
48703                         return this.$uibModal.open(this.modalOption);
48704                     };
48705                     MyModal.prototype.selectCommand = function () {
48706                         this.modalOption.templateUrl = 'templates/select-command.html';
48707                         this.modalOption.controller = 'selectCommandController';
48708                         this.modalOption.controllerAs = 'c';
48709                         this.modalOption.size = 'lg';
48710                         return this.$uibModal.open(this.modalOption);
48711                     };
48712                     MyModal.prototype.preview = function () {
48713                         this.modalOption.templateUrl = 'templates/preview.html';
48714                         this.modalOption.controller = 'previewController';
48715                         this.modalOption.controllerAs = 'c';
48716                         this.modalOption.size = 'lg';
48717                         return this.$uibModal.open(this.modalOption);
48718                     };
48719 <<<<<<< HEAD
48720                     MyModal.prototype.upload = function () {
48721                         this.modalOption.templateUrl = 'templates/upload.html';
48722                         this.modalOption.controller = 'uploadController';
48723                         this.modalOption.controllerAs = 'c';
48724                         this.modalOption.size = 'lg';
48725                         return this.$uibModal.open(this.modalOption);
48726                     };
48727 =======
48728 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
48729                     MyModal.$inject = ['$uibModal'];
48730                     return MyModal;
48731                 })();
48732                 services.MyModal = MyModal;
48733             })(services = app.services || (app.services = {}));
48734         })(app || (app = {}));
48735         var app;
48736         (function (app) {
48737             var services;
48738             (function (services) {
48739                 var WebSocket = (function () {
48740                     function WebSocket($rootScope) {
48741                         this.$rootScope = $rootScope;
48742                         this.socket = io.connect();
48743                     }
48744                     WebSocket.prototype.on = function (eventName, callback) {
48745                         var socket = this.socket;
48746                         var rootScope = this.$rootScope;
48747                         socket.on(eventName, function () {
48748                             var args = arguments;
48749                             rootScope.$apply(function () {
48750                                 callback.apply(socket, args);
48751                             });
48752                         });
48753                     };
48754                     WebSocket.prototype.emit = function (eventName, data, callback) {
48755                         var socket = this.socket;
48756                         var rootScope = this.$rootScope;
48757                         this.socket.emit(eventName, data, function () {
48758                             var args = arguments;
48759                             rootScope.$apply(function () {
48760                                 if (callback)
48761                                     callback.apply(socket, args);
48762                             });
48763                         });
48764                     };
48765                     return WebSocket;
48766                 })();
48767                 services.WebSocket = WebSocket;
48768             })(services = app.services || (app.services = {}));
48769         })(app || (app = {}));
48770         var app;
48771         (function (app) {
48772             var services;
48773             (function (services) {
48774                 var Console = (function () {
48775                     function Console(WebSocket, $rootScope) {
48776                         this.WebSocket = WebSocket;
48777                         this.$rootScope = $rootScope;
48778                         this.WebSocket = WebSocket;
48779                         this.$rootScope = $rootScope;
48780                         this.directiveIDs = [];
48781                         var directiveIDs = this.directiveIDs;
48782                         this.WebSocket.on('console', function (d) {
48783                             var id = d.id;
48784                             var message = d.message;
48785                             if (directiveIDs.indexOf(id) > -1) {
48786                                 $rootScope.$emit(id, message);
48787                             }
48788                         });
48789                     }
48790                     Console.prototype.addDirective = function (id) {
48791                         if (!(this.directiveIDs.indexOf(id) > -1)) {
48792                             this.directiveIDs.push(id);
48793                         }
48794                     };
48795                     Console.prototype.removeDirective = function (id) {
48796                         var i = this.directiveIDs.indexOf(id);
48797                         if (i > -1) {
48798                             this.directiveIDs.splice(i, 1);
48799                         }
48800                     };
48801                     Console.prototype.showIDs = function () {
48802                         console.log(this.directiveIDs);
48803                     };
48804                     return Console;
48805                 })();
48806                 services.Console = Console;
48807             })(services = app.services || (app.services = {}));
48808         })(app || (app = {}));
48809         var app;
48810         (function (app) {
48811             var directives;
48812             (function (directives) {
48813                 var Command = (function () {
48814                     function Command() {
48815                         this.restrict = 'E';
48816                         this.replace = true;
48817                         this.scope = true;
48818                         this.controller = 'commandController';
48819                         this.controllerAs = 'ctrl';
48820                         this.bindToController = {
48821                             index: '=',
48822                             name: '=',
48823                             remove: '&',
48824                             list: '='
48825                         };
48826                         this.templateUrl = 'templates/command.html';
48827                     }
48828                     Command.Factory = function () {
48829                         var directive = function () {
48830                             return new Command();
48831                         };
48832                         directive.$inject = [];
48833                         return directive;
48834                     };
48835                     return Command;
48836                 })();
48837                 directives.Command = Command;
48838                 var CommandController = (function () {
48839                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
48840                         this.APIEndPoint = APIEndPoint;
48841                         this.$scope = $scope;
48842                         this.MyModal = MyModal;
48843                         this.WebSocket = WebSocket;
48844                         this.$window = $window;
48845                         this.$rootScope = $rootScope;
48846                         this.Console = Console;
48847                         var controller = this;
48848                         this.APIEndPoint
48849                             .getOptionControlFile(this.name)
48850                             .$promise
48851                             .then(function (result) {
48852                             controller.options = result.info;
48853                         });
48854                         this.APIEndPoint
48855                             .getDirectories()
48856                             .$promise
48857                             .then(function (result) {
48858                             controller.dirs = result.info;
48859                         });
48860                         this.heading = "[" + this.index + "]: dcdFilePrint";
48861                         this.isOpen = true;
48862                         this.$scope.$on('close', function () {
48863                             controller.isOpen = false;
48864                         });
48865                         function guid() {
48866                             function s4() {
48867                                 return Math.floor((1 + Math.random()) * 0x10000)
48868                                     .toString(16)
48869                                     .substring(1);
48870                             }
48871                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
48872                                 s4() + '-' + s4() + s4() + s4();
48873                         }
48874                         this.uuid = guid();
48875                         this.Console.addDirective(this.uuid);
48876                         this.Console.showIDs();
48877                     }
48878                     CommandController.prototype.submit = function () {
48879                         var opt = [];
48880                         angular.forEach(this.options, function (option) {
48881                             var obj = {
48882                                 name: option.option,
48883                                 arguments: []
48884                             };
48885                             angular.forEach(option.arg, function (arg) {
48886                                 if (arg.input) {
48887                                     if (typeof arg.input === 'object') {
48888                                         obj.arguments.push(arg.input.name);
48889                                     }
48890                                     else {
48891                                         obj.arguments.push(arg.input);
48892                                     }
48893                                 }
48894                             });
48895                             if (obj.arguments.length > 0) {
48896                                 opt.push(obj);
48897                             }
48898                         });
48899                         var execObj = {
48900                             command: this.name,
48901                             workspace: this.workspace.fileId,
48902                             options: opt
48903                         };
48904                         this.APIEndPoint
48905                             .execute(JSON.stringify(execObj))
48906                             .then(function (result) {
48907                             console.log(result);
48908                         });
48909                     };
48910                     CommandController.prototype.removeMySelf = function (index) {
48911                         this.$scope.$destroy();
48912                         this.Console.removeDirective(this.uuid);
48913                         this.remove()(index, this.list);
48914                         this.Console.showIDs();
48915                     };
48916                     CommandController.prototype.reloadFiles = function () {
48917                         var _this = this;
48918                         var fileId = this.workspace.fileId;
48919                         this.APIEndPoint
48920                             .getFiles(fileId)
48921                             .$promise
48922                             .then(function (result) {
48923                             var status = result.status;
48924                             if (status === 'success') {
48925                                 _this.files = result.info;
48926                             }
48927                             else {
48928                                 console.log(result.message);
48929                             }
48930                         });
48931                     };
48932                     CommandController.prototype.debug = function () {
48933                         var div = angular.element(this.$window.document).find("div");
48934                         var consoleTag;
48935                         var parametersTag;
48936                         angular.forEach(div, function (v) {
48937                             if (v.className === "panel-body console") {
48938                                 consoleTag = v;
48939                             }
48940                             else if (v.className === "row parameters-console") {
48941                                 parametersTag = v;
48942                             }
48943                         });
48944                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
48945                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
48946                         consoleTag.style.height = consoleHeight;
48947                         consoleTag.style.width = consoleWidth;
48948                     };
48949                     CommandController.prototype.help = function () {
48950                         this.APIEndPoint
48951                             .help(this.name)
48952                             .then(function (result) {
48953                             console.log(result);
48954                         });
48955                     };
48956                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
48957                     return CommandController;
48958                 })();
48959                 directives.CommandController = CommandController;
48960             })(directives = app.directives || (app.directives = {}));
48961         })(app || (app = {}));
48962         var app;
48963         (function (app) {
48964             var directives;
48965             (function (directives) {
48966                 var HeaderMenu = (function () {
48967                     function HeaderMenu() {
48968                         this.restrict = 'E';
48969                         this.replace = true;
48970                         this.templateUrl = 'templates/header-menu.html';
48971                         this.controller = 'HeaderMenuController';
48972                         this.controllerAs = 'hmc';
48973                         this.scope = true;
48974                     }
48975                     HeaderMenu.Factory = function () {
48976                         var directive = function () {
48977                             return new HeaderMenu();
48978                         };
48979                         return directive;
48980                     };
48981                     return HeaderMenu;
48982                 })();
48983                 directives.HeaderMenu = HeaderMenu;
48984                 var HeaderMenuController = (function () {
48985                     function HeaderMenuController($state) {
48986                         this.$state = $state;
48987                         this.isExecution = this.$state.current.name === 'execution';
48988                         this.isWorkspace = this.$state.current.name === 'workspace';
48989                         this.isHistory = this.$state.current.name === 'history';
48990                     }
48991                     HeaderMenuController.prototype.transit = function (state) {
48992                         this.$state.go(state);
48993                     };
48994                     HeaderMenuController.$inject = ['$state'];
48995                     return HeaderMenuController;
48996                 })();
48997                 directives.HeaderMenuController = HeaderMenuController;
48998             })(directives = app.directives || (app.directives = {}));
48999         })(app || (app = {}));
49000         var app;
49001         (function (app) {
49002             var directives;
49003             (function (directives) {
49004                 var Option = (function () {
49005                     function Option() {
49006                         this.restrict = 'E';
49007                         this.replace = true;
49008                         this.controller = 'optionController';
49009                         this.bindToController = {
49010                             info: '=',
49011                             files: '='
49012                         };
49013                         this.scope = true;
49014                         this.templateUrl = 'templates/option.html';
49015                         this.controllerAs = 'ctrl';
49016                     }
49017                     Option.Factory = function () {
49018                         var directive = function () {
49019                             return new Option();
49020                         };
49021                         directive.$inject = [];
49022                         return directive;
49023                     };
49024                     return Option;
49025                 })();
49026                 directives.Option = Option;
49027                 var OptionController = (function () {
49028                     function OptionController() {
49029                         var controller = this;
49030                         angular.forEach(controller.info.arg, function (arg) {
49031                             if (arg.initialValue) {
49032                                 if (arg.formType === 'number') {
49033                                     arg.input = parseInt(arg.initialValue);
49034                                 }
49035                                 else {
49036                                     arg.input = arg.initialValue;
49037                                 }
49038                             }
49039                         });
49040                     }
49041                     OptionController.$inject = [];
49042                     return OptionController;
49043                 })();
49044                 directives.OptionController = OptionController;
49045             })(directives = app.directives || (app.directives = {}));
49046         })(app || (app = {}));
49047         var app;
49048         (function (app) {
49049             var directives;
49050             (function (directives) {
49051                 var Directory = (function () {
49052                     function Directory() {
49053                         this.restrict = 'E';
49054                         this.replace = true;
49055                         this.controller = 'directoryController';
49056                         this.controllerAs = 'ctrl';
49057                         this.bindToController = {
49058                             info: '=',
49059                             add: '&',
49060                             list: '=',
49061                             files: '='
49062                         };
49063                         this.templateUrl = 'templates/directory.html';
49064                     }
49065                     Directory.Factory = function () {
49066                         var directive = function () {
49067                             return new Directory();
49068                         };
49069                         return directive;
49070                     };
49071                     return Directory;
49072                 })();
49073                 directives.Directory = Directory;
49074                 var DirectoryController = (function () {
49075                     function DirectoryController(APIEndPoint, $scope) {
49076                         this.APIEndPoint = APIEndPoint;
49077                         this.$scope = $scope;
49078                         var controller = this;
49079                         this.APIEndPoint
49080                             .getFiles(this.info.fileId)
49081                             .$promise
49082                             .then(function (result) {
49083                             if (result.status === 'success') {
49084                                 controller.files = result.info;
49085                                 angular.forEach(result.info, function (file) {
49086                                     if (file.fileType === '0') {
49087                                         var o = file;
49088                                         if (controller.info.path === '/') {
49089                                             o.path = '/' + file.name;
49090                                         }
49091                                         else {
49092                                             o.path = controller.info.path + '/' + file.name;
49093                                         }
49094                                         controller.add()(o, controller.list);
49095                                     }
49096                                 });
49097                             }
49098                             ;
49099                         });
49100                     }
49101                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
49102                     return DirectoryController;
49103                 })();
49104                 directives.DirectoryController = DirectoryController;
49105             })(directives = app.directives || (app.directives = {}));
49106         })(app || (app = {}));
49107         var app;
49108         (function (app) {
49109 <<<<<<< HEAD
49110             var directives;
49111             (function (directives) {
49112                 var Upload = (function () {
49113                     function Upload() {
49114                         this.restrict = 'E';
49115                         this.replace = true;
49116                         this.scope = true;
49117                         this.controller = 'UploadController';
49118                         this.controllerAs = 'ctrl';
49119                         this.bindToController = {
49120                             index: '=',
49121                             name: '=',
49122                             remove: '&',
49123                             list: '='
49124                         };
49125                         this.templateUrl = 'templates/upload.html';
49126                         console.log("templates/upload.html-constructor");
49127                     }
49128                     Upload.Factory = function () {
49129                         var directive = function () {
49130                             return new Upload();
49131                         };
49132                         directive.$inject = [];
49133                         return directive;
49134                     };
49135                     return Upload;
49136                 })();
49137                 directives.Upload = Upload;
49138                 var UploadController = (function () {
49139                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
49140                         this.APIEndPoint = APIEndPoint;
49141                         this.$scope = $scope;
49142                         this.MyModal = MyModal;
49143                         this.WebSocket = WebSocket;
49144                         this.$window = $window;
49145                         this.$rootScope = $rootScope;
49146                         this.Console = Console;
49147                         var controller = this;
49148                         console.log("directive.upload-constructor");
49149                     }
49150                     UploadController.prototype.submit = function () {
49151                         console.log("submit: function not supported¥n");
49152                     };
49153                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
49154                     return UploadController;
49155                 })();
49156                 directives.UploadController = UploadController;
49157             })(directives = app.directives || (app.directives = {}));
49158         })(app || (app = {}));
49159         var app;
49160         (function (app) {
49161 =======
49162 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49163             var controllers;
49164             (function (controllers) {
49165                 var Execution = (function () {
49166                     function Execution(MyModal, $scope) {
49167                         this.MyModal = MyModal;
49168                         this.$scope = $scope;
49169                         this.commandInfoList = [];
49170                     }
49171                     ;
49172                     Execution.prototype.add = function () {
49173                         this.$scope.$broadcast('close');
49174                         var commandInfoList = this.commandInfoList;
49175                         var commandInstance = this.MyModal.selectCommand();
49176                         commandInstance
49177                             .result
49178                             .then(function (command) {
49179                             commandInfoList.push(new app.declares.CommandInfo(command));
49180                         });
49181                     };
49182                     Execution.prototype.open = function () {
49183                         var result = this.MyModal.open('SelectCommand');
49184                         console.log(result);
49185                     };
49186                     Execution.prototype.remove = function (index, list) {
49187                         list.splice(index, 1);
49188                     };
49189                     Execution.prototype.close = function () {
49190                         console.log("close");
49191                     };
49192                     Execution.$inject = ['MyModal', '$scope'];
49193                     return Execution;
49194                 })();
49195                 controllers.Execution = Execution;
49196             })(controllers = app.controllers || (app.controllers = {}));
49197         })(app || (app = {}));
49198         var app;
49199         (function (app) {
49200             var controllers;
49201             (function (controllers) {
49202                 var Workspace = (function () {
49203                     function Workspace($scope, APIEndPoint, MyModal) {
49204                         this.$scope = $scope;
49205                         this.APIEndPoint = APIEndPoint;
49206                         this.MyModal = MyModal;
49207                         this.directoryList = [];
49208                         var controller = this;
49209                         var directoryList = this.directoryList;
49210                         var o = {
49211                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
49212                             name: '',
49213                             parentId: '',
49214                             fileType: '',
49215                             createdAt: '',
49216                             updatedAt: '',
49217                             path: '/'
49218                         };
49219                         directoryList.push(o);
49220                     }
49221                     Workspace.prototype.addDirectory = function (info, directoryList) {
49222                         directoryList.push(info);
49223                     };
49224 <<<<<<< HEAD
49225                     Workspace.prototype.upload = function () {
49226                         this.MyModal.upload();
49227                     };
49228 =======
49229 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49230                     Workspace.prototype.debug = function () {
49231                         this.MyModal.preview();
49232                     };
49233                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
49234                     return Workspace;
49235                 })();
49236                 controllers.Workspace = Workspace;
49237             })(controllers = app.controllers || (app.controllers = {}));
49238         })(app || (app = {}));
49239         var app;
49240         (function (app) {
49241             var controllers;
49242             (function (controllers) {
49243                 var History = (function () {
49244                     function History($scope) {
49245                         this.page = "History";
49246                     }
49247                     History.$inject = ['$scope'];
49248                     return History;
49249                 })();
49250                 controllers.History = History;
49251             })(controllers = app.controllers || (app.controllers = {}));
49252         })(app || (app = {}));
49253         var app;
49254         (function (app) {
49255             var controllers;
49256             (function (controllers) {
49257                 var SelectCommand = (function () {
49258                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
49259                         this.APIEndPoint = APIEndPoint;
49260                         this.$modalInstance = $modalInstance;
49261                         var controller = this;
49262                         this.APIEndPoint
49263                             .getTags()
49264                             .$promise.then(function (result) {
49265                             controller.tags = result.info;
49266                         });
49267                         this.APIEndPoint
49268                             .getCommands()
49269                             .$promise.then(function (result) {
49270                             controller.commands = result.info;
49271                         });
49272                         this.currentTag = 'all';
49273                     }
49274                     SelectCommand.prototype.changeTag = function (tag) {
49275                         this.currentTag = tag;
49276                     };
49277                     SelectCommand.prototype.selectCommand = function (command) {
49278                         this.$modalInstance.close(command);
49279                     };
49280                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
49281                     return SelectCommand;
49282                 })();
49283                 controllers.SelectCommand = SelectCommand;
49284             })(controllers = app.controllers || (app.controllers = {}));
49285         })(app || (app = {}));
49286         var app;
49287         (function (app) {
49288             var controllers;
49289             (function (controllers) {
49290 <<<<<<< HEAD
49291                 var Upload = (function () {
49292                     function Upload($scope, APIEndPoint, $modalInstance) {
49293                         this.APIEndPoint = APIEndPoint;
49294                         this.$modalInstance = $modalInstance;
49295                         var controller = this;
49296                         console.log('controller.upload-controllers');
49297                     }
49298                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
49299                     return Upload;
49300                 })();
49301                 controllers.Upload = Upload;
49302             })(controllers = app.controllers || (app.controllers = {}));
49303         })(app || (app = {}));
49304         var app;
49305         (function (app) {
49306             var controllers;
49307             (function (controllers) {
49308 =======
49309 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49310                 var Preview = (function () {
49311                     function Preview($scope, APIEndPoint, $modalInstance) {
49312                         this.APIEndPoint = APIEndPoint;
49313                         this.$modalInstance = $modalInstance;
49314                         var controller = this;
49315                         console.log('preview');
49316                     }
49317                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
49318                     return Preview;
49319                 })();
49320                 controllers.Preview = Preview;
49321             })(controllers = app.controllers || (app.controllers = {}));
49322         })(app || (app = {}));
49323         var filters;
49324         (function (filters) {
49325             function Tag() {
49326                 return function (commands, tag) {
49327                     var result = [];
49328                     angular.forEach(commands, function (command) {
49329                         var flag = false;
49330                         angular.forEach(command.tags, function (value) {
49331                             if (tag === value)
49332                                 flag = true;
49333                         });
49334                         if (flag)
49335                             result.push(command);
49336                     });
49337                     return result;
49338                 };
49339             }
49340             filters.Tag = Tag;
49341         })(filters || (filters = {}));
49342         var app;
49343         (function (app) {
49344             'use strict';
49345             var appName = 'zephyr';
49346             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
49347             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
49348                 $urlRouterProvider.otherwise('/execution');
49349                 $locationProvider.html5Mode({
49350                     enabled: true,
49351                     requireBase: false
49352                 });
49353                 $stateProvider
49354                     .state('execution', {
49355                     url: '/execution',
49356                     templateUrl: 'templates/execution.html',
49357                     controller: 'executionController',
49358                     controllerAs: 'c'
49359                 })
49360                     .state('workspace', {
49361                     url: '/workspace',
49362                     templateUrl: 'templates/workspace.html',
49363                     controller: 'workspaceController',
49364                     controllerAs: 'c'
49365                 })
49366                     .state('history', {
49367                     url: '/history',
49368                     templateUrl: 'templates/history.html',
49369                     controller: 'historyController',
49370                     controllerAs: 'c'
49371                 });
49372             });
49373             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
49374             app.zephyr.service('MyModal', app.services.MyModal);
49375             app.zephyr.service('WebSocket', app.services.WebSocket);
49376             app.zephyr.service('Console', app.services.Console);
49377             app.zephyr.filter('Tag', filters.Tag);
49378             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
49379             app.zephyr.controller('previewController', app.controllers.Preview);
49380 <<<<<<< HEAD
49381             app.zephyr.controller('uploadController', app.controllers.Upload);
49382 =======
49383 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49384             app.zephyr.controller('executionController', app.controllers.Execution);
49385             app.zephyr.controller('workspaceController', app.controllers.Workspace);
49386             app.zephyr.controller('historyController', app.controllers.History);
49387             app.zephyr.controller('commandController', app.directives.CommandController);
49388             app.zephyr.controller('optionController', app.directives.OptionController);
49389             app.zephyr.controller('directoryController', app.directives.DirectoryController);
49390             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
49391 <<<<<<< HEAD
49392             app.zephyr.controller('uploadController', app.directives.UploadController);
49393 =======
49394 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49395             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
49396             app.zephyr.directive('command', app.directives.Command.Factory());
49397             app.zephyr.directive('option', app.directives.Option.Factory());
49398             app.zephyr.directive('directory', app.directives.Directory.Factory());
49399         })(app || (app = {}));
49400
49401
49402 /***/ },
49403 <<<<<<< HEAD
49404 /* 13 */
49405 =======
49406 /* 11 */
49407 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49408 /***/ function(module, exports) {
49409
49410         var app;
49411         (function (app) {
49412             var declares;
49413             (function (declares) {
49414                 var CommandInfo = (function () {
49415                     function CommandInfo(name) {
49416                         this.name = name;
49417                     }
49418                     return CommandInfo;
49419                 })();
49420                 declares.CommandInfo = CommandInfo;
49421             })(declares = app.declares || (app.declares = {}));
49422         })(app || (app = {}));
49423         var app;
49424         (function (app) {
49425             var services;
49426             (function (services) {
49427                 var APIEndPoint = (function () {
49428                     function APIEndPoint($resource, $http) {
49429                         this.$resource = $resource;
49430                         this.$http = $http;
49431                     }
49432                     APIEndPoint.prototype.resource = function (endPoint, data) {
49433                         var customAction = {
49434                             method: 'GET',
49435                             isArray: false
49436                         };
49437                         var execute = {
49438                             method: 'POST',
49439                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
49440                         };
49441                         return this.$resource(endPoint, {}, { execute: execute });
49442                     };
49443                     APIEndPoint.prototype.getOptionControlFile = function (command) {
49444                         var endPoint = '/api/v1/optionControlFile/' + command;
49445                         return this.resource(endPoint, {}).get();
49446                     };
49447                     APIEndPoint.prototype.getFiles = function (fileId) {
49448                         var endPoint = '/api/v1/workspace';
49449                         if (fileId) {
49450                             endPoint += '/' + fileId;
49451                         }
49452                         return this.resource(endPoint, {}).get();
49453                     };
49454                     APIEndPoint.prototype.getDirectories = function () {
49455                         var endPoint = '/api/v1/all/workspace/directory';
49456                         return this.resource(endPoint, {}).get();
49457                     };
49458                     APIEndPoint.prototype.getTags = function () {
49459                         var endPoint = '/api/v1/tagList';
49460                         return this.resource(endPoint, {}).get();
49461                     };
49462                     APIEndPoint.prototype.getCommands = function () {
49463                         var endPoint = '/api/v1/commandList';
49464                         return this.resource(endPoint, {}).get();
49465                     };
49466                     APIEndPoint.prototype.execute = function (data) {
49467                         var endPoint = '/api/v1/execution';
49468                         var fd = new FormData();
49469                         fd.append('data', data);
49470                         return this.$http.post(endPoint, fd, {
49471                             headers: { 'Content-Type': undefined },
49472                             transformRequest: angular.identity
49473                         });
49474                     };
49475                     APIEndPoint.prototype.debug = function () {
49476                         var endPoint = '/api/v1/debug';
49477                         return this.$http.get(endPoint);
49478                     };
49479 <<<<<<< HEAD
49480                     APIEndPoint.prototype.upload = function () {
49481                         var endPoint = '/api/v1/upload';
49482                         return this.$http.get(endPoint);
49483                     };
49484 =======
49485 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49486                     APIEndPoint.prototype.help = function (command) {
49487                         var endPoint = '/api/v1/help/' + command;
49488                         return this.$http.get(endPoint);
49489                     };
49490                     return APIEndPoint;
49491                 })();
49492                 services.APIEndPoint = APIEndPoint;
49493             })(services = app.services || (app.services = {}));
49494         })(app || (app = {}));
49495         var app;
49496         (function (app) {
49497             var services;
49498             (function (services) {
49499                 var MyModal = (function () {
49500                     function MyModal($uibModal) {
49501                         this.$uibModal = $uibModal;
49502                         this.modalOption = {
49503                             backdrop: true,
49504                             controller: null,
49505                             templateUrl: null,
49506                             size: null
49507                         };
49508                     }
49509                     MyModal.prototype.open = function (modalName) {
49510                         if (modalName === 'SelectCommand') {
49511                             this.modalOption.templateUrl = 'templates/select-command.html';
49512                             this.modalOption.size = 'lg';
49513                         }
49514                         return this.$uibModal.open(this.modalOption);
49515                     };
49516                     MyModal.prototype.selectCommand = function () {
49517                         this.modalOption.templateUrl = 'templates/select-command.html';
49518                         this.modalOption.controller = 'selectCommandController';
49519                         this.modalOption.controllerAs = 'c';
49520                         this.modalOption.size = 'lg';
49521                         return this.$uibModal.open(this.modalOption);
49522                     };
49523                     MyModal.prototype.preview = function () {
49524                         this.modalOption.templateUrl = 'templates/preview.html';
49525                         this.modalOption.controller = 'previewController';
49526                         this.modalOption.controllerAs = 'c';
49527                         this.modalOption.size = 'lg';
49528                         return this.$uibModal.open(this.modalOption);
49529                     };
49530 <<<<<<< HEAD
49531                     MyModal.prototype.upload = function () {
49532                         this.modalOption.templateUrl = 'templates/upload.html';
49533                         this.modalOption.controller = 'uploadController';
49534                         this.modalOption.controllerAs = 'c';
49535                         this.modalOption.size = 'lg';
49536                         return this.$uibModal.open(this.modalOption);
49537                     };
49538 =======
49539 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49540                     MyModal.$inject = ['$uibModal'];
49541                     return MyModal;
49542                 })();
49543                 services.MyModal = MyModal;
49544             })(services = app.services || (app.services = {}));
49545         })(app || (app = {}));
49546         var app;
49547         (function (app) {
49548             var services;
49549             (function (services) {
49550                 var WebSocket = (function () {
49551                     function WebSocket($rootScope) {
49552                         this.$rootScope = $rootScope;
49553                         this.socket = io.connect();
49554                     }
49555                     WebSocket.prototype.on = function (eventName, callback) {
49556                         var socket = this.socket;
49557                         var rootScope = this.$rootScope;
49558                         socket.on(eventName, function () {
49559                             var args = arguments;
49560                             rootScope.$apply(function () {
49561                                 callback.apply(socket, args);
49562                             });
49563                         });
49564                     };
49565                     WebSocket.prototype.emit = function (eventName, data, callback) {
49566                         var socket = this.socket;
49567                         var rootScope = this.$rootScope;
49568                         this.socket.emit(eventName, data, function () {
49569                             var args = arguments;
49570                             rootScope.$apply(function () {
49571                                 if (callback)
49572                                     callback.apply(socket, args);
49573                             });
49574                         });
49575                     };
49576                     return WebSocket;
49577                 })();
49578                 services.WebSocket = WebSocket;
49579             })(services = app.services || (app.services = {}));
49580         })(app || (app = {}));
49581         var app;
49582         (function (app) {
49583             var services;
49584             (function (services) {
49585                 var Console = (function () {
49586                     function Console(WebSocket, $rootScope) {
49587                         this.WebSocket = WebSocket;
49588                         this.$rootScope = $rootScope;
49589                         this.WebSocket = WebSocket;
49590                         this.$rootScope = $rootScope;
49591                         this.directiveIDs = [];
49592                         var directiveIDs = this.directiveIDs;
49593                         this.WebSocket.on('console', function (d) {
49594                             var id = d.id;
49595                             var message = d.message;
49596                             if (directiveIDs.indexOf(id) > -1) {
49597                                 $rootScope.$emit(id, message);
49598                             }
49599                         });
49600                     }
49601                     Console.prototype.addDirective = function (id) {
49602                         if (!(this.directiveIDs.indexOf(id) > -1)) {
49603                             this.directiveIDs.push(id);
49604                         }
49605                     };
49606                     Console.prototype.removeDirective = function (id) {
49607                         var i = this.directiveIDs.indexOf(id);
49608                         if (i > -1) {
49609                             this.directiveIDs.splice(i, 1);
49610                         }
49611                     };
49612                     Console.prototype.showIDs = function () {
49613                         console.log(this.directiveIDs);
49614                     };
49615                     return Console;
49616                 })();
49617                 services.Console = Console;
49618             })(services = app.services || (app.services = {}));
49619         })(app || (app = {}));
49620         var app;
49621         (function (app) {
49622             var directives;
49623             (function (directives) {
49624                 var Command = (function () {
49625                     function Command() {
49626                         this.restrict = 'E';
49627                         this.replace = true;
49628                         this.scope = true;
49629                         this.controller = 'commandController';
49630                         this.controllerAs = 'ctrl';
49631                         this.bindToController = {
49632                             index: '=',
49633                             name: '=',
49634                             remove: '&',
49635                             list: '='
49636                         };
49637                         this.templateUrl = 'templates/command.html';
49638                     }
49639                     Command.Factory = function () {
49640                         var directive = function () {
49641                             return new Command();
49642                         };
49643                         directive.$inject = [];
49644                         return directive;
49645                     };
49646                     return Command;
49647                 })();
49648                 directives.Command = Command;
49649                 var CommandController = (function () {
49650                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
49651                         this.APIEndPoint = APIEndPoint;
49652                         this.$scope = $scope;
49653                         this.MyModal = MyModal;
49654                         this.WebSocket = WebSocket;
49655                         this.$window = $window;
49656                         this.$rootScope = $rootScope;
49657                         this.Console = Console;
49658                         var controller = this;
49659                         this.APIEndPoint
49660                             .getOptionControlFile(this.name)
49661                             .$promise
49662                             .then(function (result) {
49663                             controller.options = result.info;
49664                         });
49665                         this.APIEndPoint
49666                             .getDirectories()
49667                             .$promise
49668                             .then(function (result) {
49669                             controller.dirs = result.info;
49670                         });
49671                         this.heading = "[" + this.index + "]: dcdFilePrint";
49672                         this.isOpen = true;
49673                         this.$scope.$on('close', function () {
49674                             controller.isOpen = false;
49675                         });
49676                         function guid() {
49677                             function s4() {
49678                                 return Math.floor((1 + Math.random()) * 0x10000)
49679                                     .toString(16)
49680                                     .substring(1);
49681                             }
49682                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
49683                                 s4() + '-' + s4() + s4() + s4();
49684                         }
49685                         this.uuid = guid();
49686                         this.Console.addDirective(this.uuid);
49687                         this.Console.showIDs();
49688                     }
49689                     CommandController.prototype.submit = function () {
49690                         var opt = [];
49691                         angular.forEach(this.options, function (option) {
49692                             var obj = {
49693                                 name: option.option,
49694                                 arguments: []
49695                             };
49696                             angular.forEach(option.arg, function (arg) {
49697                                 if (arg.input) {
49698                                     if (typeof arg.input === 'object') {
49699                                         obj.arguments.push(arg.input.name);
49700                                     }
49701                                     else {
49702                                         obj.arguments.push(arg.input);
49703                                     }
49704                                 }
49705                             });
49706                             if (obj.arguments.length > 0) {
49707                                 opt.push(obj);
49708                             }
49709                         });
49710                         var execObj = {
49711                             command: this.name,
49712                             workspace: this.workspace.fileId,
49713                             options: opt
49714                         };
49715                         this.APIEndPoint
49716                             .execute(JSON.stringify(execObj))
49717                             .then(function (result) {
49718                             console.log(result);
49719                         });
49720                     };
49721                     CommandController.prototype.removeMySelf = function (index) {
49722                         this.$scope.$destroy();
49723                         this.Console.removeDirective(this.uuid);
49724                         this.remove()(index, this.list);
49725                         this.Console.showIDs();
49726                     };
49727                     CommandController.prototype.reloadFiles = function () {
49728                         var _this = this;
49729                         var fileId = this.workspace.fileId;
49730                         this.APIEndPoint
49731                             .getFiles(fileId)
49732                             .$promise
49733                             .then(function (result) {
49734                             var status = result.status;
49735                             if (status === 'success') {
49736                                 _this.files = result.info;
49737                             }
49738                             else {
49739                                 console.log(result.message);
49740                             }
49741                         });
49742                     };
49743                     CommandController.prototype.debug = function () {
49744                         var div = angular.element(this.$window.document).find("div");
49745                         var consoleTag;
49746                         var parametersTag;
49747                         angular.forEach(div, function (v) {
49748                             if (v.className === "panel-body console") {
49749                                 consoleTag = v;
49750                             }
49751                             else if (v.className === "row parameters-console") {
49752                                 parametersTag = v;
49753                             }
49754                         });
49755                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
49756                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
49757                         consoleTag.style.height = consoleHeight;
49758                         consoleTag.style.width = consoleWidth;
49759                     };
49760                     CommandController.prototype.help = function () {
49761                         this.APIEndPoint
49762                             .help(this.name)
49763                             .then(function (result) {
49764                             console.log(result);
49765                         });
49766                     };
49767                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
49768                     return CommandController;
49769                 })();
49770                 directives.CommandController = CommandController;
49771             })(directives = app.directives || (app.directives = {}));
49772         })(app || (app = {}));
49773         var app;
49774         (function (app) {
49775             var directives;
49776             (function (directives) {
49777                 var HeaderMenu = (function () {
49778                     function HeaderMenu() {
49779                         this.restrict = 'E';
49780                         this.replace = true;
49781                         this.templateUrl = 'templates/header-menu.html';
49782                         this.controller = 'HeaderMenuController';
49783                         this.controllerAs = 'hmc';
49784                         this.scope = true;
49785                     }
49786                     HeaderMenu.Factory = function () {
49787                         var directive = function () {
49788                             return new HeaderMenu();
49789                         };
49790                         return directive;
49791                     };
49792                     return HeaderMenu;
49793                 })();
49794                 directives.HeaderMenu = HeaderMenu;
49795                 var HeaderMenuController = (function () {
49796                     function HeaderMenuController($state) {
49797                         this.$state = $state;
49798                         this.isExecution = this.$state.current.name === 'execution';
49799                         this.isWorkspace = this.$state.current.name === 'workspace';
49800                         this.isHistory = this.$state.current.name === 'history';
49801                     }
49802                     HeaderMenuController.prototype.transit = function (state) {
49803                         this.$state.go(state);
49804                     };
49805                     HeaderMenuController.$inject = ['$state'];
49806                     return HeaderMenuController;
49807                 })();
49808                 directives.HeaderMenuController = HeaderMenuController;
49809             })(directives = app.directives || (app.directives = {}));
49810         })(app || (app = {}));
49811         var app;
49812         (function (app) {
49813             var directives;
49814             (function (directives) {
49815                 var Option = (function () {
49816                     function Option() {
49817                         this.restrict = 'E';
49818                         this.replace = true;
49819                         this.controller = 'optionController';
49820                         this.bindToController = {
49821                             info: '=',
49822                             files: '='
49823                         };
49824                         this.scope = true;
49825                         this.templateUrl = 'templates/option.html';
49826                         this.controllerAs = 'ctrl';
49827                     }
49828                     Option.Factory = function () {
49829                         var directive = function () {
49830                             return new Option();
49831                         };
49832                         directive.$inject = [];
49833                         return directive;
49834                     };
49835                     return Option;
49836                 })();
49837                 directives.Option = Option;
49838                 var OptionController = (function () {
49839                     function OptionController() {
49840                         var controller = this;
49841                         angular.forEach(controller.info.arg, function (arg) {
49842                             if (arg.initialValue) {
49843                                 if (arg.formType === 'number') {
49844                                     arg.input = parseInt(arg.initialValue);
49845                                 }
49846                                 else {
49847                                     arg.input = arg.initialValue;
49848                                 }
49849                             }
49850                         });
49851                     }
49852                     OptionController.$inject = [];
49853                     return OptionController;
49854                 })();
49855                 directives.OptionController = OptionController;
49856             })(directives = app.directives || (app.directives = {}));
49857         })(app || (app = {}));
49858         var app;
49859         (function (app) {
49860             var directives;
49861             (function (directives) {
49862                 var Directory = (function () {
49863                     function Directory() {
49864                         this.restrict = 'E';
49865                         this.replace = true;
49866                         this.controller = 'directoryController';
49867                         this.controllerAs = 'ctrl';
49868                         this.bindToController = {
49869                             info: '=',
49870                             add: '&',
49871                             list: '=',
49872                             files: '='
49873                         };
49874                         this.templateUrl = 'templates/directory.html';
49875                     }
49876                     Directory.Factory = function () {
49877                         var directive = function () {
49878                             return new Directory();
49879                         };
49880                         return directive;
49881                     };
49882                     return Directory;
49883                 })();
49884                 directives.Directory = Directory;
49885                 var DirectoryController = (function () {
49886                     function DirectoryController(APIEndPoint, $scope) {
49887                         this.APIEndPoint = APIEndPoint;
49888                         this.$scope = $scope;
49889                         var controller = this;
49890                         this.APIEndPoint
49891                             .getFiles(this.info.fileId)
49892                             .$promise
49893                             .then(function (result) {
49894                             if (result.status === 'success') {
49895                                 controller.files = result.info;
49896                                 angular.forEach(result.info, function (file) {
49897                                     if (file.fileType === '0') {
49898                                         var o = file;
49899                                         if (controller.info.path === '/') {
49900                                             o.path = '/' + file.name;
49901                                         }
49902                                         else {
49903                                             o.path = controller.info.path + '/' + file.name;
49904                                         }
49905                                         controller.add()(o, controller.list);
49906                                     }
49907                                 });
49908                             }
49909                             ;
49910                         });
49911                     }
49912                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
49913                     return DirectoryController;
49914                 })();
49915                 directives.DirectoryController = DirectoryController;
49916             })(directives = app.directives || (app.directives = {}));
49917         })(app || (app = {}));
49918         var app;
49919         (function (app) {
49920 <<<<<<< HEAD
49921             var directives;
49922             (function (directives) {
49923                 var Upload = (function () {
49924                     function Upload() {
49925                         this.restrict = 'E';
49926                         this.replace = true;
49927                         this.scope = true;
49928                         this.controller = 'UploadController';
49929                         this.controllerAs = 'ctrl';
49930                         this.bindToController = {
49931                             index: '=',
49932                             name: '=',
49933                             remove: '&',
49934                             list: '='
49935                         };
49936                         this.templateUrl = 'templates/upload.html';
49937                         console.log("templates/upload.html-constructor");
49938                     }
49939                     Upload.Factory = function () {
49940                         var directive = function () {
49941                             return new Upload();
49942                         };
49943                         directive.$inject = [];
49944                         return directive;
49945                     };
49946                     return Upload;
49947                 })();
49948                 directives.Upload = Upload;
49949                 var UploadController = (function () {
49950                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
49951                         this.APIEndPoint = APIEndPoint;
49952                         this.$scope = $scope;
49953                         this.MyModal = MyModal;
49954                         this.WebSocket = WebSocket;
49955                         this.$window = $window;
49956                         this.$rootScope = $rootScope;
49957                         this.Console = Console;
49958                         var controller = this;
49959                         console.log("directive.upload-constructor");
49960                     }
49961                     UploadController.prototype.submit = function () {
49962                         console.log("submit: function not supported¥n");
49963                     };
49964                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
49965                     return UploadController;
49966                 })();
49967                 directives.UploadController = UploadController;
49968             })(directives = app.directives || (app.directives = {}));
49969         })(app || (app = {}));
49970         var app;
49971         (function (app) {
49972 =======
49973 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
49974             var controllers;
49975             (function (controllers) {
49976                 var Execution = (function () {
49977                     function Execution(MyModal, $scope) {
49978                         this.MyModal = MyModal;
49979                         this.$scope = $scope;
49980                         this.commandInfoList = [];
49981                     }
49982                     ;
49983                     Execution.prototype.add = function () {
49984                         this.$scope.$broadcast('close');
49985                         var commandInfoList = this.commandInfoList;
49986                         var commandInstance = this.MyModal.selectCommand();
49987                         commandInstance
49988                             .result
49989                             .then(function (command) {
49990                             commandInfoList.push(new app.declares.CommandInfo(command));
49991                         });
49992                     };
49993                     Execution.prototype.open = function () {
49994                         var result = this.MyModal.open('SelectCommand');
49995                         console.log(result);
49996                     };
49997                     Execution.prototype.remove = function (index, list) {
49998                         list.splice(index, 1);
49999                     };
50000                     Execution.prototype.close = function () {
50001                         console.log("close");
50002                     };
50003                     Execution.$inject = ['MyModal', '$scope'];
50004                     return Execution;
50005                 })();
50006                 controllers.Execution = Execution;
50007             })(controllers = app.controllers || (app.controllers = {}));
50008         })(app || (app = {}));
50009         var app;
50010         (function (app) {
50011             var controllers;
50012             (function (controllers) {
50013                 var Workspace = (function () {
50014                     function Workspace($scope, APIEndPoint, MyModal) {
50015                         this.$scope = $scope;
50016                         this.APIEndPoint = APIEndPoint;
50017                         this.MyModal = MyModal;
50018                         this.directoryList = [];
50019                         var controller = this;
50020                         var directoryList = this.directoryList;
50021                         var o = {
50022                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
50023                             name: '',
50024                             parentId: '',
50025                             fileType: '',
50026                             createdAt: '',
50027                             updatedAt: '',
50028                             path: '/'
50029                         };
50030                         directoryList.push(o);
50031                     }
50032                     Workspace.prototype.addDirectory = function (info, directoryList) {
50033                         directoryList.push(info);
50034                     };
50035 <<<<<<< HEAD
50036                     Workspace.prototype.upload = function () {
50037                         this.MyModal.upload();
50038                     };
50039 =======
50040 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50041                     Workspace.prototype.debug = function () {
50042                         this.MyModal.preview();
50043                     };
50044                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
50045                     return Workspace;
50046                 })();
50047                 controllers.Workspace = Workspace;
50048             })(controllers = app.controllers || (app.controllers = {}));
50049         })(app || (app = {}));
50050         var app;
50051         (function (app) {
50052             var controllers;
50053             (function (controllers) {
50054                 var History = (function () {
50055                     function History($scope) {
50056                         this.page = "History";
50057                     }
50058                     History.$inject = ['$scope'];
50059                     return History;
50060                 })();
50061                 controllers.History = History;
50062             })(controllers = app.controllers || (app.controllers = {}));
50063         })(app || (app = {}));
50064         var app;
50065         (function (app) {
50066             var controllers;
50067             (function (controllers) {
50068                 var SelectCommand = (function () {
50069                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
50070                         this.APIEndPoint = APIEndPoint;
50071                         this.$modalInstance = $modalInstance;
50072                         var controller = this;
50073                         this.APIEndPoint
50074                             .getTags()
50075                             .$promise.then(function (result) {
50076                             controller.tags = result.info;
50077                         });
50078                         this.APIEndPoint
50079                             .getCommands()
50080                             .$promise.then(function (result) {
50081                             controller.commands = result.info;
50082                         });
50083                         this.currentTag = 'all';
50084                     }
50085                     SelectCommand.prototype.changeTag = function (tag) {
50086                         this.currentTag = tag;
50087                     };
50088                     SelectCommand.prototype.selectCommand = function (command) {
50089                         this.$modalInstance.close(command);
50090                     };
50091                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
50092                     return SelectCommand;
50093                 })();
50094                 controllers.SelectCommand = SelectCommand;
50095             })(controllers = app.controllers || (app.controllers = {}));
50096         })(app || (app = {}));
50097         var app;
50098         (function (app) {
50099             var controllers;
50100             (function (controllers) {
50101 <<<<<<< HEAD
50102                 var Upload = (function () {
50103                     function Upload($scope, APIEndPoint, $modalInstance) {
50104                         this.APIEndPoint = APIEndPoint;
50105                         this.$modalInstance = $modalInstance;
50106                         var controller = this;
50107                         console.log('controller.upload-controllers');
50108                     }
50109                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
50110                     return Upload;
50111                 })();
50112                 controllers.Upload = Upload;
50113             })(controllers = app.controllers || (app.controllers = {}));
50114         })(app || (app = {}));
50115         var app;
50116         (function (app) {
50117             var controllers;
50118             (function (controllers) {
50119 =======
50120 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50121                 var Preview = (function () {
50122                     function Preview($scope, APIEndPoint, $modalInstance) {
50123                         this.APIEndPoint = APIEndPoint;
50124                         this.$modalInstance = $modalInstance;
50125                         var controller = this;
50126                         console.log('preview');
50127                     }
50128                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
50129                     return Preview;
50130                 })();
50131                 controllers.Preview = Preview;
50132             })(controllers = app.controllers || (app.controllers = {}));
50133         })(app || (app = {}));
50134         var filters;
50135         (function (filters) {
50136             function Tag() {
50137                 return function (commands, tag) {
50138                     var result = [];
50139                     angular.forEach(commands, function (command) {
50140                         var flag = false;
50141                         angular.forEach(command.tags, function (value) {
50142                             if (tag === value)
50143                                 flag = true;
50144                         });
50145                         if (flag)
50146                             result.push(command);
50147                     });
50148                     return result;
50149                 };
50150             }
50151             filters.Tag = Tag;
50152         })(filters || (filters = {}));
50153         var app;
50154         (function (app) {
50155             'use strict';
50156             var appName = 'zephyr';
50157             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
50158             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
50159                 $urlRouterProvider.otherwise('/execution');
50160                 $locationProvider.html5Mode({
50161                     enabled: true,
50162                     requireBase: false
50163                 });
50164                 $stateProvider
50165                     .state('execution', {
50166                     url: '/execution',
50167                     templateUrl: 'templates/execution.html',
50168                     controller: 'executionController',
50169                     controllerAs: 'c'
50170                 })
50171                     .state('workspace', {
50172                     url: '/workspace',
50173                     templateUrl: 'templates/workspace.html',
50174                     controller: 'workspaceController',
50175                     controllerAs: 'c'
50176                 })
50177                     .state('history', {
50178                     url: '/history',
50179                     templateUrl: 'templates/history.html',
50180                     controller: 'historyController',
50181                     controllerAs: 'c'
50182                 });
50183             });
50184             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
50185             app.zephyr.service('MyModal', app.services.MyModal);
50186             app.zephyr.service('WebSocket', app.services.WebSocket);
50187             app.zephyr.service('Console', app.services.Console);
50188             app.zephyr.filter('Tag', filters.Tag);
50189             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
50190             app.zephyr.controller('previewController', app.controllers.Preview);
50191 <<<<<<< HEAD
50192             app.zephyr.controller('uploadController', app.controllers.Upload);
50193 =======
50194 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50195             app.zephyr.controller('executionController', app.controllers.Execution);
50196             app.zephyr.controller('workspaceController', app.controllers.Workspace);
50197             app.zephyr.controller('historyController', app.controllers.History);
50198             app.zephyr.controller('commandController', app.directives.CommandController);
50199             app.zephyr.controller('optionController', app.directives.OptionController);
50200             app.zephyr.controller('directoryController', app.directives.DirectoryController);
50201             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
50202 <<<<<<< HEAD
50203             app.zephyr.controller('uploadController', app.directives.UploadController);
50204 =======
50205 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50206             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
50207             app.zephyr.directive('command', app.directives.Command.Factory());
50208             app.zephyr.directive('option', app.directives.Option.Factory());
50209             app.zephyr.directive('directory', app.directives.Directory.Factory());
50210         })(app || (app = {}));
50211
50212
50213 /***/ },
50214 <<<<<<< HEAD
50215 /* 14 */
50216 =======
50217 /* 12 */
50218 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50219 /***/ function(module, exports) {
50220
50221         var app;
50222         (function (app) {
50223             var declares;
50224             (function (declares) {
50225                 var CommandInfo = (function () {
50226                     function CommandInfo(name) {
50227                         this.name = name;
50228                     }
50229                     return CommandInfo;
50230                 })();
50231                 declares.CommandInfo = CommandInfo;
50232             })(declares = app.declares || (app.declares = {}));
50233         })(app || (app = {}));
50234         var app;
50235         (function (app) {
50236             var services;
50237             (function (services) {
50238                 var APIEndPoint = (function () {
50239                     function APIEndPoint($resource, $http) {
50240                         this.$resource = $resource;
50241                         this.$http = $http;
50242                     }
50243                     APIEndPoint.prototype.resource = function (endPoint, data) {
50244                         var customAction = {
50245                             method: 'GET',
50246                             isArray: false
50247                         };
50248                         var execute = {
50249                             method: 'POST',
50250                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
50251                         };
50252                         return this.$resource(endPoint, {}, { execute: execute });
50253                     };
50254                     APIEndPoint.prototype.getOptionControlFile = function (command) {
50255                         var endPoint = '/api/v1/optionControlFile/' + command;
50256                         return this.resource(endPoint, {}).get();
50257                     };
50258                     APIEndPoint.prototype.getFiles = function (fileId) {
50259                         var endPoint = '/api/v1/workspace';
50260                         if (fileId) {
50261                             endPoint += '/' + fileId;
50262                         }
50263                         return this.resource(endPoint, {}).get();
50264                     };
50265                     APIEndPoint.prototype.getDirectories = function () {
50266                         var endPoint = '/api/v1/all/workspace/directory';
50267                         return this.resource(endPoint, {}).get();
50268                     };
50269                     APIEndPoint.prototype.getTags = function () {
50270                         var endPoint = '/api/v1/tagList';
50271                         return this.resource(endPoint, {}).get();
50272                     };
50273                     APIEndPoint.prototype.getCommands = function () {
50274                         var endPoint = '/api/v1/commandList';
50275                         return this.resource(endPoint, {}).get();
50276                     };
50277                     APIEndPoint.prototype.execute = function (data) {
50278                         var endPoint = '/api/v1/execution';
50279                         var fd = new FormData();
50280                         fd.append('data', data);
50281                         return this.$http.post(endPoint, fd, {
50282                             headers: { 'Content-Type': undefined },
50283                             transformRequest: angular.identity
50284                         });
50285                     };
50286                     APIEndPoint.prototype.debug = function () {
50287                         var endPoint = '/api/v1/debug';
50288                         return this.$http.get(endPoint);
50289                     };
50290 <<<<<<< HEAD
50291                     APIEndPoint.prototype.upload = function () {
50292                         var endPoint = '/api/v1/upload';
50293                         return this.$http.get(endPoint);
50294                     };
50295 =======
50296 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50297                     APIEndPoint.prototype.help = function (command) {
50298                         var endPoint = '/api/v1/help/' + command;
50299                         return this.$http.get(endPoint);
50300                     };
50301                     return APIEndPoint;
50302                 })();
50303                 services.APIEndPoint = APIEndPoint;
50304             })(services = app.services || (app.services = {}));
50305         })(app || (app = {}));
50306         var app;
50307         (function (app) {
50308             var services;
50309             (function (services) {
50310                 var MyModal = (function () {
50311                     function MyModal($uibModal) {
50312                         this.$uibModal = $uibModal;
50313                         this.modalOption = {
50314                             backdrop: true,
50315                             controller: null,
50316                             templateUrl: null,
50317                             size: null
50318                         };
50319                     }
50320                     MyModal.prototype.open = function (modalName) {
50321                         if (modalName === 'SelectCommand') {
50322                             this.modalOption.templateUrl = 'templates/select-command.html';
50323                             this.modalOption.size = 'lg';
50324                         }
50325                         return this.$uibModal.open(this.modalOption);
50326                     };
50327                     MyModal.prototype.selectCommand = function () {
50328                         this.modalOption.templateUrl = 'templates/select-command.html';
50329                         this.modalOption.controller = 'selectCommandController';
50330                         this.modalOption.controllerAs = 'c';
50331                         this.modalOption.size = 'lg';
50332                         return this.$uibModal.open(this.modalOption);
50333                     };
50334                     MyModal.prototype.preview = function () {
50335                         this.modalOption.templateUrl = 'templates/preview.html';
50336                         this.modalOption.controller = 'previewController';
50337                         this.modalOption.controllerAs = 'c';
50338                         this.modalOption.size = 'lg';
50339                         return this.$uibModal.open(this.modalOption);
50340                     };
50341 <<<<<<< HEAD
50342                     MyModal.prototype.upload = function () {
50343                         this.modalOption.templateUrl = 'templates/upload.html';
50344                         this.modalOption.controller = 'uploadController';
50345                         this.modalOption.controllerAs = 'c';
50346                         this.modalOption.size = 'lg';
50347                         return this.$uibModal.open(this.modalOption);
50348                     };
50349 =======
50350 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50351                     MyModal.$inject = ['$uibModal'];
50352                     return MyModal;
50353                 })();
50354                 services.MyModal = MyModal;
50355             })(services = app.services || (app.services = {}));
50356         })(app || (app = {}));
50357         var app;
50358         (function (app) {
50359             var services;
50360             (function (services) {
50361                 var WebSocket = (function () {
50362                     function WebSocket($rootScope) {
50363                         this.$rootScope = $rootScope;
50364                         this.socket = io.connect();
50365                     }
50366                     WebSocket.prototype.on = function (eventName, callback) {
50367                         var socket = this.socket;
50368                         var rootScope = this.$rootScope;
50369                         socket.on(eventName, function () {
50370                             var args = arguments;
50371                             rootScope.$apply(function () {
50372                                 callback.apply(socket, args);
50373                             });
50374                         });
50375                     };
50376                     WebSocket.prototype.emit = function (eventName, data, callback) {
50377                         var socket = this.socket;
50378                         var rootScope = this.$rootScope;
50379                         this.socket.emit(eventName, data, function () {
50380                             var args = arguments;
50381                             rootScope.$apply(function () {
50382                                 if (callback)
50383                                     callback.apply(socket, args);
50384                             });
50385                         });
50386                     };
50387                     return WebSocket;
50388                 })();
50389                 services.WebSocket = WebSocket;
50390             })(services = app.services || (app.services = {}));
50391         })(app || (app = {}));
50392         var app;
50393         (function (app) {
50394             var services;
50395             (function (services) {
50396                 var Console = (function () {
50397                     function Console(WebSocket, $rootScope) {
50398                         this.WebSocket = WebSocket;
50399                         this.$rootScope = $rootScope;
50400                         this.WebSocket = WebSocket;
50401                         this.$rootScope = $rootScope;
50402                         this.directiveIDs = [];
50403                         var directiveIDs = this.directiveIDs;
50404                         this.WebSocket.on('console', function (d) {
50405                             var id = d.id;
50406                             var message = d.message;
50407                             if (directiveIDs.indexOf(id) > -1) {
50408                                 $rootScope.$emit(id, message);
50409                             }
50410                         });
50411                     }
50412                     Console.prototype.addDirective = function (id) {
50413                         if (!(this.directiveIDs.indexOf(id) > -1)) {
50414                             this.directiveIDs.push(id);
50415                         }
50416                     };
50417                     Console.prototype.removeDirective = function (id) {
50418                         var i = this.directiveIDs.indexOf(id);
50419                         if (i > -1) {
50420                             this.directiveIDs.splice(i, 1);
50421                         }
50422                     };
50423                     Console.prototype.showIDs = function () {
50424                         console.log(this.directiveIDs);
50425                     };
50426                     return Console;
50427                 })();
50428                 services.Console = Console;
50429             })(services = app.services || (app.services = {}));
50430         })(app || (app = {}));
50431         var app;
50432         (function (app) {
50433             var directives;
50434             (function (directives) {
50435                 var Command = (function () {
50436                     function Command() {
50437                         this.restrict = 'E';
50438                         this.replace = true;
50439                         this.scope = true;
50440                         this.controller = 'commandController';
50441                         this.controllerAs = 'ctrl';
50442                         this.bindToController = {
50443                             index: '=',
50444                             name: '=',
50445                             remove: '&',
50446                             list: '='
50447                         };
50448                         this.templateUrl = 'templates/command.html';
50449                     }
50450                     Command.Factory = function () {
50451                         var directive = function () {
50452                             return new Command();
50453                         };
50454                         directive.$inject = [];
50455                         return directive;
50456                     };
50457                     return Command;
50458                 })();
50459                 directives.Command = Command;
50460                 var CommandController = (function () {
50461                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
50462                         this.APIEndPoint = APIEndPoint;
50463                         this.$scope = $scope;
50464                         this.MyModal = MyModal;
50465                         this.WebSocket = WebSocket;
50466                         this.$window = $window;
50467                         this.$rootScope = $rootScope;
50468                         this.Console = Console;
50469                         var controller = this;
50470                         this.APIEndPoint
50471                             .getOptionControlFile(this.name)
50472                             .$promise
50473                             .then(function (result) {
50474                             controller.options = result.info;
50475                         });
50476                         this.APIEndPoint
50477                             .getDirectories()
50478                             .$promise
50479                             .then(function (result) {
50480                             controller.dirs = result.info;
50481                         });
50482                         this.heading = "[" + this.index + "]: dcdFilePrint";
50483                         this.isOpen = true;
50484                         this.$scope.$on('close', function () {
50485                             controller.isOpen = false;
50486                         });
50487                         function guid() {
50488                             function s4() {
50489                                 return Math.floor((1 + Math.random()) * 0x10000)
50490                                     .toString(16)
50491                                     .substring(1);
50492                             }
50493                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
50494                                 s4() + '-' + s4() + s4() + s4();
50495                         }
50496                         this.uuid = guid();
50497                         this.Console.addDirective(this.uuid);
50498                         this.Console.showIDs();
50499                     }
50500                     CommandController.prototype.submit = function () {
50501                         var opt = [];
50502                         angular.forEach(this.options, function (option) {
50503                             var obj = {
50504                                 name: option.option,
50505                                 arguments: []
50506                             };
50507                             angular.forEach(option.arg, function (arg) {
50508                                 if (arg.input) {
50509                                     if (typeof arg.input === 'object') {
50510                                         obj.arguments.push(arg.input.name);
50511                                     }
50512                                     else {
50513                                         obj.arguments.push(arg.input);
50514                                     }
50515                                 }
50516                             });
50517                             if (obj.arguments.length > 0) {
50518                                 opt.push(obj);
50519                             }
50520                         });
50521                         var execObj = {
50522                             command: this.name,
50523                             workspace: this.workspace.fileId,
50524                             options: opt
50525                         };
50526                         this.APIEndPoint
50527                             .execute(JSON.stringify(execObj))
50528                             .then(function (result) {
50529                             console.log(result);
50530                         });
50531                     };
50532                     CommandController.prototype.removeMySelf = function (index) {
50533                         this.$scope.$destroy();
50534                         this.Console.removeDirective(this.uuid);
50535                         this.remove()(index, this.list);
50536                         this.Console.showIDs();
50537                     };
50538                     CommandController.prototype.reloadFiles = function () {
50539                         var _this = this;
50540                         var fileId = this.workspace.fileId;
50541                         this.APIEndPoint
50542                             .getFiles(fileId)
50543                             .$promise
50544                             .then(function (result) {
50545                             var status = result.status;
50546                             if (status === 'success') {
50547                                 _this.files = result.info;
50548                             }
50549                             else {
50550                                 console.log(result.message);
50551                             }
50552                         });
50553                     };
50554                     CommandController.prototype.debug = function () {
50555                         var div = angular.element(this.$window.document).find("div");
50556                         var consoleTag;
50557                         var parametersTag;
50558                         angular.forEach(div, function (v) {
50559                             if (v.className === "panel-body console") {
50560                                 consoleTag = v;
50561                             }
50562                             else if (v.className === "row parameters-console") {
50563                                 parametersTag = v;
50564                             }
50565                         });
50566                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
50567                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
50568                         consoleTag.style.height = consoleHeight;
50569                         consoleTag.style.width = consoleWidth;
50570                     };
50571                     CommandController.prototype.help = function () {
50572                         this.APIEndPoint
50573                             .help(this.name)
50574                             .then(function (result) {
50575                             console.log(result);
50576                         });
50577                     };
50578                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
50579                     return CommandController;
50580                 })();
50581                 directives.CommandController = CommandController;
50582             })(directives = app.directives || (app.directives = {}));
50583         })(app || (app = {}));
50584         var app;
50585         (function (app) {
50586             var directives;
50587             (function (directives) {
50588                 var HeaderMenu = (function () {
50589                     function HeaderMenu() {
50590                         this.restrict = 'E';
50591                         this.replace = true;
50592                         this.templateUrl = 'templates/header-menu.html';
50593                         this.controller = 'HeaderMenuController';
50594                         this.controllerAs = 'hmc';
50595                         this.scope = true;
50596                     }
50597                     HeaderMenu.Factory = function () {
50598                         var directive = function () {
50599                             return new HeaderMenu();
50600                         };
50601                         return directive;
50602                     };
50603                     return HeaderMenu;
50604                 })();
50605                 directives.HeaderMenu = HeaderMenu;
50606                 var HeaderMenuController = (function () {
50607                     function HeaderMenuController($state) {
50608                         this.$state = $state;
50609                         this.isExecution = this.$state.current.name === 'execution';
50610                         this.isWorkspace = this.$state.current.name === 'workspace';
50611                         this.isHistory = this.$state.current.name === 'history';
50612                     }
50613                     HeaderMenuController.prototype.transit = function (state) {
50614                         this.$state.go(state);
50615                     };
50616                     HeaderMenuController.$inject = ['$state'];
50617                     return HeaderMenuController;
50618                 })();
50619                 directives.HeaderMenuController = HeaderMenuController;
50620             })(directives = app.directives || (app.directives = {}));
50621         })(app || (app = {}));
50622         var app;
50623         (function (app) {
50624             var directives;
50625             (function (directives) {
50626                 var Option = (function () {
50627                     function Option() {
50628                         this.restrict = 'E';
50629                         this.replace = true;
50630                         this.controller = 'optionController';
50631                         this.bindToController = {
50632                             info: '=',
50633                             files: '='
50634                         };
50635                         this.scope = true;
50636                         this.templateUrl = 'templates/option.html';
50637                         this.controllerAs = 'ctrl';
50638                     }
50639                     Option.Factory = function () {
50640                         var directive = function () {
50641                             return new Option();
50642                         };
50643                         directive.$inject = [];
50644                         return directive;
50645                     };
50646                     return Option;
50647                 })();
50648                 directives.Option = Option;
50649                 var OptionController = (function () {
50650                     function OptionController() {
50651                         var controller = this;
50652                         angular.forEach(controller.info.arg, function (arg) {
50653                             if (arg.initialValue) {
50654                                 if (arg.formType === 'number') {
50655                                     arg.input = parseInt(arg.initialValue);
50656                                 }
50657                                 else {
50658                                     arg.input = arg.initialValue;
50659                                 }
50660                             }
50661                         });
50662                     }
50663                     OptionController.$inject = [];
50664                     return OptionController;
50665                 })();
50666                 directives.OptionController = OptionController;
50667             })(directives = app.directives || (app.directives = {}));
50668         })(app || (app = {}));
50669         var app;
50670         (function (app) {
50671             var directives;
50672             (function (directives) {
50673                 var Directory = (function () {
50674                     function Directory() {
50675                         this.restrict = 'E';
50676                         this.replace = true;
50677                         this.controller = 'directoryController';
50678                         this.controllerAs = 'ctrl';
50679                         this.bindToController = {
50680                             info: '=',
50681                             add: '&',
50682                             list: '=',
50683                             files: '='
50684                         };
50685                         this.templateUrl = 'templates/directory.html';
50686                     }
50687                     Directory.Factory = function () {
50688                         var directive = function () {
50689                             return new Directory();
50690                         };
50691                         return directive;
50692                     };
50693                     return Directory;
50694                 })();
50695                 directives.Directory = Directory;
50696                 var DirectoryController = (function () {
50697                     function DirectoryController(APIEndPoint, $scope) {
50698                         this.APIEndPoint = APIEndPoint;
50699                         this.$scope = $scope;
50700                         var controller = this;
50701                         this.APIEndPoint
50702                             .getFiles(this.info.fileId)
50703                             .$promise
50704                             .then(function (result) {
50705                             if (result.status === 'success') {
50706                                 controller.files = result.info;
50707                                 angular.forEach(result.info, function (file) {
50708                                     if (file.fileType === '0') {
50709                                         var o = file;
50710                                         if (controller.info.path === '/') {
50711                                             o.path = '/' + file.name;
50712                                         }
50713                                         else {
50714                                             o.path = controller.info.path + '/' + file.name;
50715                                         }
50716                                         controller.add()(o, controller.list);
50717                                     }
50718                                 });
50719                             }
50720                             ;
50721                         });
50722                     }
50723                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
50724                     return DirectoryController;
50725                 })();
50726                 directives.DirectoryController = DirectoryController;
50727             })(directives = app.directives || (app.directives = {}));
50728         })(app || (app = {}));
50729         var app;
50730         (function (app) {
50731 <<<<<<< HEAD
50732             var directives;
50733             (function (directives) {
50734                 var Upload = (function () {
50735                     function Upload() {
50736                         this.restrict = 'E';
50737                         this.replace = true;
50738                         this.scope = true;
50739                         this.controller = 'UploadController';
50740                         this.controllerAs = 'ctrl';
50741                         this.bindToController = {
50742                             index: '=',
50743                             name: '=',
50744                             remove: '&',
50745                             list: '='
50746                         };
50747                         this.templateUrl = 'templates/upload.html';
50748                         console.log("templates/upload.html-constructor");
50749                     }
50750                     Upload.Factory = function () {
50751                         var directive = function () {
50752                             return new Upload();
50753                         };
50754                         directive.$inject = [];
50755                         return directive;
50756                     };
50757                     return Upload;
50758                 })();
50759                 directives.Upload = Upload;
50760                 var UploadController = (function () {
50761                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
50762                         this.APIEndPoint = APIEndPoint;
50763                         this.$scope = $scope;
50764                         this.MyModal = MyModal;
50765                         this.WebSocket = WebSocket;
50766                         this.$window = $window;
50767                         this.$rootScope = $rootScope;
50768                         this.Console = Console;
50769                         var controller = this;
50770                         console.log("directive.upload-constructor");
50771                     }
50772                     UploadController.prototype.submit = function () {
50773                         console.log("submit: function not supported¥n");
50774                     };
50775                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
50776                     return UploadController;
50777                 })();
50778                 directives.UploadController = UploadController;
50779             })(directives = app.directives || (app.directives = {}));
50780         })(app || (app = {}));
50781         var app;
50782         (function (app) {
50783 =======
50784 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50785             var controllers;
50786             (function (controllers) {
50787                 var Execution = (function () {
50788                     function Execution(MyModal, $scope) {
50789                         this.MyModal = MyModal;
50790                         this.$scope = $scope;
50791                         this.commandInfoList = [];
50792                     }
50793                     ;
50794                     Execution.prototype.add = function () {
50795                         this.$scope.$broadcast('close');
50796                         var commandInfoList = this.commandInfoList;
50797                         var commandInstance = this.MyModal.selectCommand();
50798                         commandInstance
50799                             .result
50800                             .then(function (command) {
50801                             commandInfoList.push(new app.declares.CommandInfo(command));
50802                         });
50803                     };
50804                     Execution.prototype.open = function () {
50805                         var result = this.MyModal.open('SelectCommand');
50806                         console.log(result);
50807                     };
50808                     Execution.prototype.remove = function (index, list) {
50809                         list.splice(index, 1);
50810                     };
50811                     Execution.prototype.close = function () {
50812                         console.log("close");
50813                     };
50814                     Execution.$inject = ['MyModal', '$scope'];
50815                     return Execution;
50816                 })();
50817                 controllers.Execution = Execution;
50818             })(controllers = app.controllers || (app.controllers = {}));
50819         })(app || (app = {}));
50820         var app;
50821         (function (app) {
50822             var controllers;
50823             (function (controllers) {
50824                 var Workspace = (function () {
50825                     function Workspace($scope, APIEndPoint, MyModal) {
50826                         this.$scope = $scope;
50827                         this.APIEndPoint = APIEndPoint;
50828                         this.MyModal = MyModal;
50829                         this.directoryList = [];
50830                         var controller = this;
50831                         var directoryList = this.directoryList;
50832                         var o = {
50833                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
50834                             name: '',
50835                             parentId: '',
50836                             fileType: '',
50837                             createdAt: '',
50838                             updatedAt: '',
50839                             path: '/'
50840                         };
50841                         directoryList.push(o);
50842                     }
50843                     Workspace.prototype.addDirectory = function (info, directoryList) {
50844                         directoryList.push(info);
50845                     };
50846 <<<<<<< HEAD
50847                     Workspace.prototype.upload = function () {
50848                         this.MyModal.upload();
50849                     };
50850 =======
50851 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50852                     Workspace.prototype.debug = function () {
50853                         this.MyModal.preview();
50854                     };
50855                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
50856                     return Workspace;
50857                 })();
50858                 controllers.Workspace = Workspace;
50859             })(controllers = app.controllers || (app.controllers = {}));
50860         })(app || (app = {}));
50861         var app;
50862         (function (app) {
50863             var controllers;
50864             (function (controllers) {
50865                 var History = (function () {
50866                     function History($scope) {
50867                         this.page = "History";
50868                     }
50869                     History.$inject = ['$scope'];
50870                     return History;
50871                 })();
50872                 controllers.History = History;
50873             })(controllers = app.controllers || (app.controllers = {}));
50874         })(app || (app = {}));
50875         var app;
50876         (function (app) {
50877             var controllers;
50878             (function (controllers) {
50879                 var SelectCommand = (function () {
50880                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
50881                         this.APIEndPoint = APIEndPoint;
50882                         this.$modalInstance = $modalInstance;
50883                         var controller = this;
50884                         this.APIEndPoint
50885                             .getTags()
50886                             .$promise.then(function (result) {
50887                             controller.tags = result.info;
50888                         });
50889                         this.APIEndPoint
50890                             .getCommands()
50891                             .$promise.then(function (result) {
50892                             controller.commands = result.info;
50893                         });
50894                         this.currentTag = 'all';
50895                     }
50896                     SelectCommand.prototype.changeTag = function (tag) {
50897                         this.currentTag = tag;
50898                     };
50899                     SelectCommand.prototype.selectCommand = function (command) {
50900                         this.$modalInstance.close(command);
50901                     };
50902                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
50903                     return SelectCommand;
50904                 })();
50905                 controllers.SelectCommand = SelectCommand;
50906             })(controllers = app.controllers || (app.controllers = {}));
50907         })(app || (app = {}));
50908         var app;
50909         (function (app) {
50910             var controllers;
50911             (function (controllers) {
50912 <<<<<<< HEAD
50913                 var Upload = (function () {
50914                     function Upload($scope, APIEndPoint, $modalInstance) {
50915                         this.APIEndPoint = APIEndPoint;
50916                         this.$modalInstance = $modalInstance;
50917                         var controller = this;
50918                         console.log('controller.upload-controllers');
50919                     }
50920                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
50921                     return Upload;
50922                 })();
50923                 controllers.Upload = Upload;
50924             })(controllers = app.controllers || (app.controllers = {}));
50925         })(app || (app = {}));
50926         var app;
50927         (function (app) {
50928             var controllers;
50929             (function (controllers) {
50930 =======
50931 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
50932                 var Preview = (function () {
50933                     function Preview($scope, APIEndPoint, $modalInstance) {
50934                         this.APIEndPoint = APIEndPoint;
50935                         this.$modalInstance = $modalInstance;
50936                         var controller = this;
50937                         console.log('preview');
50938                     }
50939                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
50940                     return Preview;
50941                 })();
50942                 controllers.Preview = Preview;
50943             })(controllers = app.controllers || (app.controllers = {}));
50944         })(app || (app = {}));
50945         var filters;
50946         (function (filters) {
50947             function Tag() {
50948                 return function (commands, tag) {
50949                     var result = [];
50950                     angular.forEach(commands, function (command) {
50951                         var flag = false;
50952                         angular.forEach(command.tags, function (value) {
50953                             if (tag === value)
50954                                 flag = true;
50955                         });
50956                         if (flag)
50957                             result.push(command);
50958                     });
50959                     return result;
50960                 };
50961             }
50962             filters.Tag = Tag;
50963         })(filters || (filters = {}));
50964         var app;
50965         (function (app) {
50966             'use strict';
50967             var appName = 'zephyr';
50968             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
50969             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
50970                 $urlRouterProvider.otherwise('/execution');
50971                 $locationProvider.html5Mode({
50972                     enabled: true,
50973                     requireBase: false
50974                 });
50975                 $stateProvider
50976                     .state('execution', {
50977                     url: '/execution',
50978                     templateUrl: 'templates/execution.html',
50979                     controller: 'executionController',
50980                     controllerAs: 'c'
50981                 })
50982                     .state('workspace', {
50983                     url: '/workspace',
50984                     templateUrl: 'templates/workspace.html',
50985                     controller: 'workspaceController',
50986                     controllerAs: 'c'
50987                 })
50988                     .state('history', {
50989                     url: '/history',
50990                     templateUrl: 'templates/history.html',
50991                     controller: 'historyController',
50992                     controllerAs: 'c'
50993                 });
50994             });
50995             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
50996             app.zephyr.service('MyModal', app.services.MyModal);
50997             app.zephyr.service('WebSocket', app.services.WebSocket);
50998             app.zephyr.service('Console', app.services.Console);
50999             app.zephyr.filter('Tag', filters.Tag);
51000             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
51001             app.zephyr.controller('previewController', app.controllers.Preview);
51002 <<<<<<< HEAD
51003             app.zephyr.controller('uploadController', app.controllers.Upload);
51004 =======
51005 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51006             app.zephyr.controller('executionController', app.controllers.Execution);
51007             app.zephyr.controller('workspaceController', app.controllers.Workspace);
51008             app.zephyr.controller('historyController', app.controllers.History);
51009             app.zephyr.controller('commandController', app.directives.CommandController);
51010             app.zephyr.controller('optionController', app.directives.OptionController);
51011             app.zephyr.controller('directoryController', app.directives.DirectoryController);
51012             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
51013 <<<<<<< HEAD
51014             app.zephyr.controller('uploadController', app.directives.UploadController);
51015 =======
51016 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51017             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
51018             app.zephyr.directive('command', app.directives.Command.Factory());
51019             app.zephyr.directive('option', app.directives.Option.Factory());
51020             app.zephyr.directive('directory', app.directives.Directory.Factory());
51021         })(app || (app = {}));
51022
51023
51024 /***/ },
51025 <<<<<<< HEAD
51026 /* 15 */
51027 =======
51028 /* 13 */
51029 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51030 /***/ function(module, exports) {
51031
51032         var app;
51033         (function (app) {
51034             var declares;
51035             (function (declares) {
51036                 var CommandInfo = (function () {
51037                     function CommandInfo(name) {
51038                         this.name = name;
51039                     }
51040                     return CommandInfo;
51041                 })();
51042                 declares.CommandInfo = CommandInfo;
51043             })(declares = app.declares || (app.declares = {}));
51044         })(app || (app = {}));
51045         var app;
51046         (function (app) {
51047             var services;
51048             (function (services) {
51049                 var APIEndPoint = (function () {
51050                     function APIEndPoint($resource, $http) {
51051                         this.$resource = $resource;
51052                         this.$http = $http;
51053                     }
51054                     APIEndPoint.prototype.resource = function (endPoint, data) {
51055                         var customAction = {
51056                             method: 'GET',
51057                             isArray: false
51058                         };
51059                         var execute = {
51060                             method: 'POST',
51061                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
51062                         };
51063                         return this.$resource(endPoint, {}, { execute: execute });
51064                     };
51065                     APIEndPoint.prototype.getOptionControlFile = function (command) {
51066                         var endPoint = '/api/v1/optionControlFile/' + command;
51067                         return this.resource(endPoint, {}).get();
51068                     };
51069                     APIEndPoint.prototype.getFiles = function (fileId) {
51070                         var endPoint = '/api/v1/workspace';
51071                         if (fileId) {
51072                             endPoint += '/' + fileId;
51073                         }
51074                         return this.resource(endPoint, {}).get();
51075                     };
51076                     APIEndPoint.prototype.getDirectories = function () {
51077                         var endPoint = '/api/v1/all/workspace/directory';
51078                         return this.resource(endPoint, {}).get();
51079                     };
51080                     APIEndPoint.prototype.getTags = function () {
51081                         var endPoint = '/api/v1/tagList';
51082                         return this.resource(endPoint, {}).get();
51083                     };
51084                     APIEndPoint.prototype.getCommands = function () {
51085                         var endPoint = '/api/v1/commandList';
51086                         return this.resource(endPoint, {}).get();
51087                     };
51088                     APIEndPoint.prototype.execute = function (data) {
51089                         var endPoint = '/api/v1/execution';
51090                         var fd = new FormData();
51091                         fd.append('data', data);
51092                         return this.$http.post(endPoint, fd, {
51093                             headers: { 'Content-Type': undefined },
51094                             transformRequest: angular.identity
51095                         });
51096                     };
51097                     APIEndPoint.prototype.debug = function () {
51098                         var endPoint = '/api/v1/debug';
51099                         return this.$http.get(endPoint);
51100                     };
51101 <<<<<<< HEAD
51102                     APIEndPoint.prototype.upload = function () {
51103                         var endPoint = '/api/v1/upload';
51104                         return this.$http.get(endPoint);
51105                     };
51106 =======
51107 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51108                     APIEndPoint.prototype.help = function (command) {
51109                         var endPoint = '/api/v1/help/' + command;
51110                         return this.$http.get(endPoint);
51111                     };
51112                     return APIEndPoint;
51113                 })();
51114                 services.APIEndPoint = APIEndPoint;
51115             })(services = app.services || (app.services = {}));
51116         })(app || (app = {}));
51117         var app;
51118         (function (app) {
51119             var services;
51120             (function (services) {
51121                 var MyModal = (function () {
51122                     function MyModal($uibModal) {
51123                         this.$uibModal = $uibModal;
51124                         this.modalOption = {
51125                             backdrop: true,
51126                             controller: null,
51127                             templateUrl: null,
51128                             size: null
51129                         };
51130                     }
51131                     MyModal.prototype.open = function (modalName) {
51132                         if (modalName === 'SelectCommand') {
51133                             this.modalOption.templateUrl = 'templates/select-command.html';
51134                             this.modalOption.size = 'lg';
51135                         }
51136                         return this.$uibModal.open(this.modalOption);
51137                     };
51138                     MyModal.prototype.selectCommand = function () {
51139                         this.modalOption.templateUrl = 'templates/select-command.html';
51140                         this.modalOption.controller = 'selectCommandController';
51141                         this.modalOption.controllerAs = 'c';
51142                         this.modalOption.size = 'lg';
51143                         return this.$uibModal.open(this.modalOption);
51144                     };
51145                     MyModal.prototype.preview = function () {
51146                         this.modalOption.templateUrl = 'templates/preview.html';
51147                         this.modalOption.controller = 'previewController';
51148                         this.modalOption.controllerAs = 'c';
51149                         this.modalOption.size = 'lg';
51150                         return this.$uibModal.open(this.modalOption);
51151                     };
51152 <<<<<<< HEAD
51153                     MyModal.prototype.upload = function () {
51154                         this.modalOption.templateUrl = 'templates/upload.html';
51155                         this.modalOption.controller = 'uploadController';
51156                         this.modalOption.controllerAs = 'c';
51157                         this.modalOption.size = 'lg';
51158                         return this.$uibModal.open(this.modalOption);
51159                     };
51160 =======
51161 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51162                     MyModal.$inject = ['$uibModal'];
51163                     return MyModal;
51164                 })();
51165                 services.MyModal = MyModal;
51166             })(services = app.services || (app.services = {}));
51167         })(app || (app = {}));
51168         var app;
51169         (function (app) {
51170             var services;
51171             (function (services) {
51172                 var WebSocket = (function () {
51173                     function WebSocket($rootScope) {
51174                         this.$rootScope = $rootScope;
51175                         this.socket = io.connect();
51176                     }
51177                     WebSocket.prototype.on = function (eventName, callback) {
51178                         var socket = this.socket;
51179                         var rootScope = this.$rootScope;
51180                         socket.on(eventName, function () {
51181                             var args = arguments;
51182                             rootScope.$apply(function () {
51183                                 callback.apply(socket, args);
51184                             });
51185                         });
51186                     };
51187                     WebSocket.prototype.emit = function (eventName, data, callback) {
51188                         var socket = this.socket;
51189                         var rootScope = this.$rootScope;
51190                         this.socket.emit(eventName, data, function () {
51191                             var args = arguments;
51192                             rootScope.$apply(function () {
51193                                 if (callback)
51194                                     callback.apply(socket, args);
51195                             });
51196                         });
51197                     };
51198                     return WebSocket;
51199                 })();
51200                 services.WebSocket = WebSocket;
51201             })(services = app.services || (app.services = {}));
51202         })(app || (app = {}));
51203         var app;
51204         (function (app) {
51205             var services;
51206             (function (services) {
51207                 var Console = (function () {
51208                     function Console(WebSocket, $rootScope) {
51209                         this.WebSocket = WebSocket;
51210                         this.$rootScope = $rootScope;
51211                         this.WebSocket = WebSocket;
51212                         this.$rootScope = $rootScope;
51213                         this.directiveIDs = [];
51214                         var directiveIDs = this.directiveIDs;
51215                         this.WebSocket.on('console', function (d) {
51216                             var id = d.id;
51217                             var message = d.message;
51218                             if (directiveIDs.indexOf(id) > -1) {
51219                                 $rootScope.$emit(id, message);
51220                             }
51221                         });
51222                     }
51223                     Console.prototype.addDirective = function (id) {
51224                         if (!(this.directiveIDs.indexOf(id) > -1)) {
51225                             this.directiveIDs.push(id);
51226                         }
51227                     };
51228                     Console.prototype.removeDirective = function (id) {
51229                         var i = this.directiveIDs.indexOf(id);
51230                         if (i > -1) {
51231                             this.directiveIDs.splice(i, 1);
51232                         }
51233                     };
51234                     Console.prototype.showIDs = function () {
51235                         console.log(this.directiveIDs);
51236                     };
51237                     return Console;
51238                 })();
51239                 services.Console = Console;
51240             })(services = app.services || (app.services = {}));
51241         })(app || (app = {}));
51242         var app;
51243         (function (app) {
51244             var directives;
51245             (function (directives) {
51246                 var Command = (function () {
51247                     function Command() {
51248                         this.restrict = 'E';
51249                         this.replace = true;
51250                         this.scope = true;
51251                         this.controller = 'commandController';
51252                         this.controllerAs = 'ctrl';
51253                         this.bindToController = {
51254                             index: '=',
51255                             name: '=',
51256                             remove: '&',
51257                             list: '='
51258                         };
51259                         this.templateUrl = 'templates/command.html';
51260                     }
51261                     Command.Factory = function () {
51262                         var directive = function () {
51263                             return new Command();
51264                         };
51265                         directive.$inject = [];
51266                         return directive;
51267                     };
51268                     return Command;
51269                 })();
51270                 directives.Command = Command;
51271                 var CommandController = (function () {
51272                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
51273                         this.APIEndPoint = APIEndPoint;
51274                         this.$scope = $scope;
51275                         this.MyModal = MyModal;
51276                         this.WebSocket = WebSocket;
51277                         this.$window = $window;
51278                         this.$rootScope = $rootScope;
51279                         this.Console = Console;
51280                         var controller = this;
51281                         this.APIEndPoint
51282                             .getOptionControlFile(this.name)
51283                             .$promise
51284                             .then(function (result) {
51285                             controller.options = result.info;
51286                         });
51287                         this.APIEndPoint
51288                             .getDirectories()
51289                             .$promise
51290                             .then(function (result) {
51291                             controller.dirs = result.info;
51292                         });
51293                         this.heading = "[" + this.index + "]: dcdFilePrint";
51294                         this.isOpen = true;
51295                         this.$scope.$on('close', function () {
51296                             controller.isOpen = false;
51297                         });
51298                         function guid() {
51299                             function s4() {
51300                                 return Math.floor((1 + Math.random()) * 0x10000)
51301                                     .toString(16)
51302                                     .substring(1);
51303                             }
51304                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
51305                                 s4() + '-' + s4() + s4() + s4();
51306                         }
51307                         this.uuid = guid();
51308                         this.Console.addDirective(this.uuid);
51309                         this.Console.showIDs();
51310                     }
51311                     CommandController.prototype.submit = function () {
51312                         var opt = [];
51313                         angular.forEach(this.options, function (option) {
51314                             var obj = {
51315                                 name: option.option,
51316                                 arguments: []
51317                             };
51318                             angular.forEach(option.arg, function (arg) {
51319                                 if (arg.input) {
51320                                     if (typeof arg.input === 'object') {
51321                                         obj.arguments.push(arg.input.name);
51322                                     }
51323                                     else {
51324                                         obj.arguments.push(arg.input);
51325                                     }
51326                                 }
51327                             });
51328                             if (obj.arguments.length > 0) {
51329                                 opt.push(obj);
51330                             }
51331                         });
51332                         var execObj = {
51333                             command: this.name,
51334                             workspace: this.workspace.fileId,
51335                             options: opt
51336                         };
51337                         this.APIEndPoint
51338                             .execute(JSON.stringify(execObj))
51339                             .then(function (result) {
51340                             console.log(result);
51341                         });
51342                     };
51343                     CommandController.prototype.removeMySelf = function (index) {
51344                         this.$scope.$destroy();
51345                         this.Console.removeDirective(this.uuid);
51346                         this.remove()(index, this.list);
51347                         this.Console.showIDs();
51348                     };
51349                     CommandController.prototype.reloadFiles = function () {
51350                         var _this = this;
51351                         var fileId = this.workspace.fileId;
51352                         this.APIEndPoint
51353                             .getFiles(fileId)
51354                             .$promise
51355                             .then(function (result) {
51356                             var status = result.status;
51357                             if (status === 'success') {
51358                                 _this.files = result.info;
51359                             }
51360                             else {
51361                                 console.log(result.message);
51362                             }
51363                         });
51364                     };
51365                     CommandController.prototype.debug = function () {
51366                         var div = angular.element(this.$window.document).find("div");
51367                         var consoleTag;
51368                         var parametersTag;
51369                         angular.forEach(div, function (v) {
51370                             if (v.className === "panel-body console") {
51371                                 consoleTag = v;
51372                             }
51373                             else if (v.className === "row parameters-console") {
51374                                 parametersTag = v;
51375                             }
51376                         });
51377                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
51378                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
51379                         consoleTag.style.height = consoleHeight;
51380                         consoleTag.style.width = consoleWidth;
51381                     };
51382                     CommandController.prototype.help = function () {
51383                         this.APIEndPoint
51384                             .help(this.name)
51385                             .then(function (result) {
51386                             console.log(result);
51387                         });
51388                     };
51389                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
51390                     return CommandController;
51391                 })();
51392                 directives.CommandController = CommandController;
51393             })(directives = app.directives || (app.directives = {}));
51394         })(app || (app = {}));
51395         var app;
51396         (function (app) {
51397             var directives;
51398             (function (directives) {
51399                 var HeaderMenu = (function () {
51400                     function HeaderMenu() {
51401                         this.restrict = 'E';
51402                         this.replace = true;
51403                         this.templateUrl = 'templates/header-menu.html';
51404                         this.controller = 'HeaderMenuController';
51405                         this.controllerAs = 'hmc';
51406                         this.scope = true;
51407                     }
51408                     HeaderMenu.Factory = function () {
51409                         var directive = function () {
51410                             return new HeaderMenu();
51411                         };
51412                         return directive;
51413                     };
51414                     return HeaderMenu;
51415                 })();
51416                 directives.HeaderMenu = HeaderMenu;
51417                 var HeaderMenuController = (function () {
51418                     function HeaderMenuController($state) {
51419                         this.$state = $state;
51420                         this.isExecution = this.$state.current.name === 'execution';
51421                         this.isWorkspace = this.$state.current.name === 'workspace';
51422                         this.isHistory = this.$state.current.name === 'history';
51423                     }
51424                     HeaderMenuController.prototype.transit = function (state) {
51425                         this.$state.go(state);
51426                     };
51427                     HeaderMenuController.$inject = ['$state'];
51428                     return HeaderMenuController;
51429                 })();
51430                 directives.HeaderMenuController = HeaderMenuController;
51431             })(directives = app.directives || (app.directives = {}));
51432         })(app || (app = {}));
51433         var app;
51434         (function (app) {
51435             var directives;
51436             (function (directives) {
51437                 var Option = (function () {
51438                     function Option() {
51439                         this.restrict = 'E';
51440                         this.replace = true;
51441                         this.controller = 'optionController';
51442                         this.bindToController = {
51443                             info: '=',
51444                             files: '='
51445                         };
51446                         this.scope = true;
51447                         this.templateUrl = 'templates/option.html';
51448                         this.controllerAs = 'ctrl';
51449                     }
51450                     Option.Factory = function () {
51451                         var directive = function () {
51452                             return new Option();
51453                         };
51454                         directive.$inject = [];
51455                         return directive;
51456                     };
51457                     return Option;
51458                 })();
51459                 directives.Option = Option;
51460                 var OptionController = (function () {
51461                     function OptionController() {
51462                         var controller = this;
51463                         angular.forEach(controller.info.arg, function (arg) {
51464                             if (arg.initialValue) {
51465                                 if (arg.formType === 'number') {
51466                                     arg.input = parseInt(arg.initialValue);
51467                                 }
51468                                 else {
51469                                     arg.input = arg.initialValue;
51470                                 }
51471                             }
51472                         });
51473                     }
51474                     OptionController.$inject = [];
51475                     return OptionController;
51476                 })();
51477                 directives.OptionController = OptionController;
51478             })(directives = app.directives || (app.directives = {}));
51479         })(app || (app = {}));
51480         var app;
51481         (function (app) {
51482             var directives;
51483             (function (directives) {
51484                 var Directory = (function () {
51485                     function Directory() {
51486                         this.restrict = 'E';
51487                         this.replace = true;
51488                         this.controller = 'directoryController';
51489                         this.controllerAs = 'ctrl';
51490                         this.bindToController = {
51491                             info: '=',
51492                             add: '&',
51493                             list: '=',
51494                             files: '='
51495                         };
51496                         this.templateUrl = 'templates/directory.html';
51497                     }
51498                     Directory.Factory = function () {
51499                         var directive = function () {
51500                             return new Directory();
51501                         };
51502                         return directive;
51503                     };
51504                     return Directory;
51505                 })();
51506                 directives.Directory = Directory;
51507                 var DirectoryController = (function () {
51508                     function DirectoryController(APIEndPoint, $scope) {
51509                         this.APIEndPoint = APIEndPoint;
51510                         this.$scope = $scope;
51511                         var controller = this;
51512                         this.APIEndPoint
51513                             .getFiles(this.info.fileId)
51514                             .$promise
51515                             .then(function (result) {
51516                             if (result.status === 'success') {
51517                                 controller.files = result.info;
51518                                 angular.forEach(result.info, function (file) {
51519                                     if (file.fileType === '0') {
51520                                         var o = file;
51521                                         if (controller.info.path === '/') {
51522                                             o.path = '/' + file.name;
51523                                         }
51524                                         else {
51525                                             o.path = controller.info.path + '/' + file.name;
51526                                         }
51527                                         controller.add()(o, controller.list);
51528                                     }
51529                                 });
51530                             }
51531                             ;
51532                         });
51533                     }
51534                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
51535                     return DirectoryController;
51536                 })();
51537                 directives.DirectoryController = DirectoryController;
51538             })(directives = app.directives || (app.directives = {}));
51539         })(app || (app = {}));
51540         var app;
51541         (function (app) {
51542 <<<<<<< HEAD
51543             var directives;
51544             (function (directives) {
51545                 var Upload = (function () {
51546                     function Upload() {
51547                         this.restrict = 'E';
51548                         this.replace = true;
51549                         this.scope = true;
51550                         this.controller = 'UploadController';
51551                         this.controllerAs = 'ctrl';
51552                         this.bindToController = {
51553                             index: '=',
51554                             name: '=',
51555                             remove: '&',
51556                             list: '='
51557                         };
51558                         this.templateUrl = 'templates/upload.html';
51559                         console.log("templates/upload.html-constructor");
51560                     }
51561                     Upload.Factory = function () {
51562                         var directive = function () {
51563                             return new Upload();
51564                         };
51565                         directive.$inject = [];
51566                         return directive;
51567                     };
51568                     return Upload;
51569                 })();
51570                 directives.Upload = Upload;
51571                 var UploadController = (function () {
51572                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
51573                         this.APIEndPoint = APIEndPoint;
51574                         this.$scope = $scope;
51575                         this.MyModal = MyModal;
51576                         this.WebSocket = WebSocket;
51577                         this.$window = $window;
51578                         this.$rootScope = $rootScope;
51579                         this.Console = Console;
51580                         var controller = this;
51581                         console.log("directive.upload-constructor");
51582                     }
51583                     UploadController.prototype.submit = function () {
51584                         console.log("submit: function not supported¥n");
51585                     };
51586                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
51587                     return UploadController;
51588                 })();
51589                 directives.UploadController = UploadController;
51590             })(directives = app.directives || (app.directives = {}));
51591         })(app || (app = {}));
51592         var app;
51593         (function (app) {
51594 =======
51595 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51596             var controllers;
51597             (function (controllers) {
51598                 var Execution = (function () {
51599                     function Execution(MyModal, $scope) {
51600                         this.MyModal = MyModal;
51601                         this.$scope = $scope;
51602                         this.commandInfoList = [];
51603                     }
51604                     ;
51605                     Execution.prototype.add = function () {
51606                         this.$scope.$broadcast('close');
51607                         var commandInfoList = this.commandInfoList;
51608                         var commandInstance = this.MyModal.selectCommand();
51609                         commandInstance
51610                             .result
51611                             .then(function (command) {
51612                             commandInfoList.push(new app.declares.CommandInfo(command));
51613                         });
51614                     };
51615                     Execution.prototype.open = function () {
51616                         var result = this.MyModal.open('SelectCommand');
51617                         console.log(result);
51618                     };
51619                     Execution.prototype.remove = function (index, list) {
51620                         list.splice(index, 1);
51621                     };
51622                     Execution.prototype.close = function () {
51623                         console.log("close");
51624                     };
51625                     Execution.$inject = ['MyModal', '$scope'];
51626                     return Execution;
51627                 })();
51628                 controllers.Execution = Execution;
51629             })(controllers = app.controllers || (app.controllers = {}));
51630         })(app || (app = {}));
51631         var app;
51632         (function (app) {
51633             var controllers;
51634             (function (controllers) {
51635                 var Workspace = (function () {
51636                     function Workspace($scope, APIEndPoint, MyModal) {
51637                         this.$scope = $scope;
51638                         this.APIEndPoint = APIEndPoint;
51639                         this.MyModal = MyModal;
51640                         this.directoryList = [];
51641                         var controller = this;
51642                         var directoryList = this.directoryList;
51643                         var o = {
51644                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
51645                             name: '',
51646                             parentId: '',
51647                             fileType: '',
51648                             createdAt: '',
51649                             updatedAt: '',
51650                             path: '/'
51651                         };
51652                         directoryList.push(o);
51653                     }
51654                     Workspace.prototype.addDirectory = function (info, directoryList) {
51655                         directoryList.push(info);
51656                     };
51657 <<<<<<< HEAD
51658                     Workspace.prototype.upload = function () {
51659                         this.MyModal.upload();
51660                     };
51661 =======
51662 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51663                     Workspace.prototype.debug = function () {
51664                         this.MyModal.preview();
51665                     };
51666                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
51667                     return Workspace;
51668                 })();
51669                 controllers.Workspace = Workspace;
51670             })(controllers = app.controllers || (app.controllers = {}));
51671         })(app || (app = {}));
51672         var app;
51673         (function (app) {
51674             var controllers;
51675             (function (controllers) {
51676                 var History = (function () {
51677                     function History($scope) {
51678                         this.page = "History";
51679                     }
51680                     History.$inject = ['$scope'];
51681                     return History;
51682                 })();
51683                 controllers.History = History;
51684             })(controllers = app.controllers || (app.controllers = {}));
51685         })(app || (app = {}));
51686         var app;
51687         (function (app) {
51688             var controllers;
51689             (function (controllers) {
51690                 var SelectCommand = (function () {
51691                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
51692                         this.APIEndPoint = APIEndPoint;
51693                         this.$modalInstance = $modalInstance;
51694                         var controller = this;
51695                         this.APIEndPoint
51696                             .getTags()
51697                             .$promise.then(function (result) {
51698                             controller.tags = result.info;
51699                         });
51700                         this.APIEndPoint
51701                             .getCommands()
51702                             .$promise.then(function (result) {
51703                             controller.commands = result.info;
51704                         });
51705                         this.currentTag = 'all';
51706                     }
51707                     SelectCommand.prototype.changeTag = function (tag) {
51708                         this.currentTag = tag;
51709                     };
51710                     SelectCommand.prototype.selectCommand = function (command) {
51711                         this.$modalInstance.close(command);
51712                     };
51713                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
51714                     return SelectCommand;
51715                 })();
51716                 controllers.SelectCommand = SelectCommand;
51717             })(controllers = app.controllers || (app.controllers = {}));
51718         })(app || (app = {}));
51719         var app;
51720         (function (app) {
51721             var controllers;
51722             (function (controllers) {
51723 <<<<<<< HEAD
51724                 var Upload = (function () {
51725                     function Upload($scope, APIEndPoint, $modalInstance) {
51726                         this.APIEndPoint = APIEndPoint;
51727                         this.$modalInstance = $modalInstance;
51728                         var controller = this;
51729                         console.log('controller.upload-controllers');
51730                     }
51731                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
51732                     return Upload;
51733                 })();
51734                 controllers.Upload = Upload;
51735             })(controllers = app.controllers || (app.controllers = {}));
51736         })(app || (app = {}));
51737         var app;
51738         (function (app) {
51739             var controllers;
51740             (function (controllers) {
51741 =======
51742 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51743                 var Preview = (function () {
51744                     function Preview($scope, APIEndPoint, $modalInstance) {
51745                         this.APIEndPoint = APIEndPoint;
51746                         this.$modalInstance = $modalInstance;
51747                         var controller = this;
51748                         console.log('preview');
51749                     }
51750                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
51751                     return Preview;
51752                 })();
51753                 controllers.Preview = Preview;
51754             })(controllers = app.controllers || (app.controllers = {}));
51755         })(app || (app = {}));
51756         var filters;
51757         (function (filters) {
51758             function Tag() {
51759                 return function (commands, tag) {
51760                     var result = [];
51761                     angular.forEach(commands, function (command) {
51762                         var flag = false;
51763                         angular.forEach(command.tags, function (value) {
51764                             if (tag === value)
51765                                 flag = true;
51766                         });
51767                         if (flag)
51768                             result.push(command);
51769                     });
51770                     return result;
51771                 };
51772             }
51773             filters.Tag = Tag;
51774         })(filters || (filters = {}));
51775         var app;
51776         (function (app) {
51777             'use strict';
51778             var appName = 'zephyr';
51779             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
51780             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
51781                 $urlRouterProvider.otherwise('/execution');
51782                 $locationProvider.html5Mode({
51783                     enabled: true,
51784                     requireBase: false
51785                 });
51786                 $stateProvider
51787                     .state('execution', {
51788                     url: '/execution',
51789                     templateUrl: 'templates/execution.html',
51790                     controller: 'executionController',
51791                     controllerAs: 'c'
51792                 })
51793                     .state('workspace', {
51794                     url: '/workspace',
51795                     templateUrl: 'templates/workspace.html',
51796                     controller: 'workspaceController',
51797                     controllerAs: 'c'
51798                 })
51799                     .state('history', {
51800                     url: '/history',
51801                     templateUrl: 'templates/history.html',
51802                     controller: 'historyController',
51803                     controllerAs: 'c'
51804                 });
51805             });
51806             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
51807             app.zephyr.service('MyModal', app.services.MyModal);
51808             app.zephyr.service('WebSocket', app.services.WebSocket);
51809             app.zephyr.service('Console', app.services.Console);
51810             app.zephyr.filter('Tag', filters.Tag);
51811             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
51812             app.zephyr.controller('previewController', app.controllers.Preview);
51813 <<<<<<< HEAD
51814             app.zephyr.controller('uploadController', app.controllers.Upload);
51815 =======
51816 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51817             app.zephyr.controller('executionController', app.controllers.Execution);
51818             app.zephyr.controller('workspaceController', app.controllers.Workspace);
51819             app.zephyr.controller('historyController', app.controllers.History);
51820             app.zephyr.controller('commandController', app.directives.CommandController);
51821             app.zephyr.controller('optionController', app.directives.OptionController);
51822             app.zephyr.controller('directoryController', app.directives.DirectoryController);
51823             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
51824 <<<<<<< HEAD
51825             app.zephyr.controller('uploadController', app.directives.UploadController);
51826 =======
51827 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51828             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
51829             app.zephyr.directive('command', app.directives.Command.Factory());
51830             app.zephyr.directive('option', app.directives.Option.Factory());
51831             app.zephyr.directive('directory', app.directives.Directory.Factory());
51832         })(app || (app = {}));
51833
51834
51835 /***/ },
51836 <<<<<<< HEAD
51837 /* 16 */
51838 =======
51839 /* 14 */
51840 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51841 /***/ function(module, exports) {
51842
51843         var app;
51844         (function (app) {
51845             var declares;
51846             (function (declares) {
51847                 var CommandInfo = (function () {
51848                     function CommandInfo(name) {
51849                         this.name = name;
51850                     }
51851                     return CommandInfo;
51852                 })();
51853                 declares.CommandInfo = CommandInfo;
51854             })(declares = app.declares || (app.declares = {}));
51855         })(app || (app = {}));
51856         var app;
51857         (function (app) {
51858             var services;
51859             (function (services) {
51860                 var APIEndPoint = (function () {
51861                     function APIEndPoint($resource, $http) {
51862                         this.$resource = $resource;
51863                         this.$http = $http;
51864                     }
51865                     APIEndPoint.prototype.resource = function (endPoint, data) {
51866                         var customAction = {
51867                             method: 'GET',
51868                             isArray: false
51869                         };
51870                         var execute = {
51871                             method: 'POST',
51872                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
51873                         };
51874                         return this.$resource(endPoint, {}, { execute: execute });
51875                     };
51876                     APIEndPoint.prototype.getOptionControlFile = function (command) {
51877                         var endPoint = '/api/v1/optionControlFile/' + command;
51878                         return this.resource(endPoint, {}).get();
51879                     };
51880                     APIEndPoint.prototype.getFiles = function (fileId) {
51881                         var endPoint = '/api/v1/workspace';
51882                         if (fileId) {
51883                             endPoint += '/' + fileId;
51884                         }
51885                         return this.resource(endPoint, {}).get();
51886                     };
51887                     APIEndPoint.prototype.getDirectories = function () {
51888                         var endPoint = '/api/v1/all/workspace/directory';
51889                         return this.resource(endPoint, {}).get();
51890                     };
51891                     APIEndPoint.prototype.getTags = function () {
51892                         var endPoint = '/api/v1/tagList';
51893                         return this.resource(endPoint, {}).get();
51894                     };
51895                     APIEndPoint.prototype.getCommands = function () {
51896                         var endPoint = '/api/v1/commandList';
51897                         return this.resource(endPoint, {}).get();
51898                     };
51899                     APIEndPoint.prototype.execute = function (data) {
51900                         var endPoint = '/api/v1/execution';
51901                         var fd = new FormData();
51902                         fd.append('data', data);
51903                         return this.$http.post(endPoint, fd, {
51904                             headers: { 'Content-Type': undefined },
51905                             transformRequest: angular.identity
51906                         });
51907                     };
51908                     APIEndPoint.prototype.debug = function () {
51909                         var endPoint = '/api/v1/debug';
51910                         return this.$http.get(endPoint);
51911                     };
51912 <<<<<<< HEAD
51913                     APIEndPoint.prototype.upload = function () {
51914                         var endPoint = '/api/v1/upload';
51915                         return this.$http.get(endPoint);
51916                     };
51917 =======
51918 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51919                     APIEndPoint.prototype.help = function (command) {
51920                         var endPoint = '/api/v1/help/' + command;
51921                         return this.$http.get(endPoint);
51922                     };
51923                     return APIEndPoint;
51924                 })();
51925                 services.APIEndPoint = APIEndPoint;
51926             })(services = app.services || (app.services = {}));
51927         })(app || (app = {}));
51928         var app;
51929         (function (app) {
51930             var services;
51931             (function (services) {
51932                 var MyModal = (function () {
51933                     function MyModal($uibModal) {
51934                         this.$uibModal = $uibModal;
51935                         this.modalOption = {
51936                             backdrop: true,
51937                             controller: null,
51938                             templateUrl: null,
51939                             size: null
51940                         };
51941                     }
51942                     MyModal.prototype.open = function (modalName) {
51943                         if (modalName === 'SelectCommand') {
51944                             this.modalOption.templateUrl = 'templates/select-command.html';
51945                             this.modalOption.size = 'lg';
51946                         }
51947                         return this.$uibModal.open(this.modalOption);
51948                     };
51949                     MyModal.prototype.selectCommand = function () {
51950                         this.modalOption.templateUrl = 'templates/select-command.html';
51951                         this.modalOption.controller = 'selectCommandController';
51952                         this.modalOption.controllerAs = 'c';
51953                         this.modalOption.size = 'lg';
51954                         return this.$uibModal.open(this.modalOption);
51955                     };
51956                     MyModal.prototype.preview = function () {
51957                         this.modalOption.templateUrl = 'templates/preview.html';
51958                         this.modalOption.controller = 'previewController';
51959                         this.modalOption.controllerAs = 'c';
51960                         this.modalOption.size = 'lg';
51961                         return this.$uibModal.open(this.modalOption);
51962                     };
51963 <<<<<<< HEAD
51964                     MyModal.prototype.upload = function () {
51965                         this.modalOption.templateUrl = 'templates/upload.html';
51966                         this.modalOption.controller = 'uploadController';
51967                         this.modalOption.controllerAs = 'c';
51968                         this.modalOption.size = 'lg';
51969                         return this.$uibModal.open(this.modalOption);
51970                     };
51971 =======
51972 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
51973                     MyModal.$inject = ['$uibModal'];
51974                     return MyModal;
51975                 })();
51976                 services.MyModal = MyModal;
51977             })(services = app.services || (app.services = {}));
51978         })(app || (app = {}));
51979         var app;
51980         (function (app) {
51981             var services;
51982             (function (services) {
51983                 var WebSocket = (function () {
51984                     function WebSocket($rootScope) {
51985                         this.$rootScope = $rootScope;
51986                         this.socket = io.connect();
51987                     }
51988                     WebSocket.prototype.on = function (eventName, callback) {
51989                         var socket = this.socket;
51990                         var rootScope = this.$rootScope;
51991                         socket.on(eventName, function () {
51992                             var args = arguments;
51993                             rootScope.$apply(function () {
51994                                 callback.apply(socket, args);
51995                             });
51996                         });
51997                     };
51998                     WebSocket.prototype.emit = function (eventName, data, callback) {
51999                         var socket = this.socket;
52000                         var rootScope = this.$rootScope;
52001                         this.socket.emit(eventName, data, function () {
52002                             var args = arguments;
52003                             rootScope.$apply(function () {
52004                                 if (callback)
52005                                     callback.apply(socket, args);
52006                             });
52007                         });
52008                     };
52009                     return WebSocket;
52010                 })();
52011                 services.WebSocket = WebSocket;
52012             })(services = app.services || (app.services = {}));
52013         })(app || (app = {}));
52014         var app;
52015         (function (app) {
52016             var services;
52017             (function (services) {
52018                 var Console = (function () {
52019                     function Console(WebSocket, $rootScope) {
52020                         this.WebSocket = WebSocket;
52021                         this.$rootScope = $rootScope;
52022                         this.WebSocket = WebSocket;
52023                         this.$rootScope = $rootScope;
52024                         this.directiveIDs = [];
52025                         var directiveIDs = this.directiveIDs;
52026                         this.WebSocket.on('console', function (d) {
52027                             var id = d.id;
52028                             var message = d.message;
52029                             if (directiveIDs.indexOf(id) > -1) {
52030                                 $rootScope.$emit(id, message);
52031                             }
52032                         });
52033                     }
52034                     Console.prototype.addDirective = function (id) {
52035                         if (!(this.directiveIDs.indexOf(id) > -1)) {
52036                             this.directiveIDs.push(id);
52037                         }
52038                     };
52039                     Console.prototype.removeDirective = function (id) {
52040                         var i = this.directiveIDs.indexOf(id);
52041                         if (i > -1) {
52042                             this.directiveIDs.splice(i, 1);
52043                         }
52044                     };
52045                     Console.prototype.showIDs = function () {
52046                         console.log(this.directiveIDs);
52047                     };
52048                     return Console;
52049                 })();
52050                 services.Console = Console;
52051             })(services = app.services || (app.services = {}));
52052         })(app || (app = {}));
52053         var app;
52054         (function (app) {
52055             var directives;
52056             (function (directives) {
52057                 var Command = (function () {
52058                     function Command() {
52059                         this.restrict = 'E';
52060                         this.replace = true;
52061                         this.scope = true;
52062                         this.controller = 'commandController';
52063                         this.controllerAs = 'ctrl';
52064                         this.bindToController = {
52065                             index: '=',
52066                             name: '=',
52067                             remove: '&',
52068                             list: '='
52069                         };
52070                         this.templateUrl = 'templates/command.html';
52071                     }
52072                     Command.Factory = function () {
52073                         var directive = function () {
52074                             return new Command();
52075                         };
52076                         directive.$inject = [];
52077                         return directive;
52078                     };
52079                     return Command;
52080                 })();
52081                 directives.Command = Command;
52082                 var CommandController = (function () {
52083                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
52084                         this.APIEndPoint = APIEndPoint;
52085                         this.$scope = $scope;
52086                         this.MyModal = MyModal;
52087                         this.WebSocket = WebSocket;
52088                         this.$window = $window;
52089                         this.$rootScope = $rootScope;
52090                         this.Console = Console;
52091                         var controller = this;
52092                         this.APIEndPoint
52093                             .getOptionControlFile(this.name)
52094                             .$promise
52095                             .then(function (result) {
52096                             controller.options = result.info;
52097                         });
52098                         this.APIEndPoint
52099                             .getDirectories()
52100                             .$promise
52101                             .then(function (result) {
52102                             controller.dirs = result.info;
52103                         });
52104                         this.heading = "[" + this.index + "]: dcdFilePrint";
52105                         this.isOpen = true;
52106                         this.$scope.$on('close', function () {
52107                             controller.isOpen = false;
52108                         });
52109                         function guid() {
52110                             function s4() {
52111                                 return Math.floor((1 + Math.random()) * 0x10000)
52112                                     .toString(16)
52113                                     .substring(1);
52114                             }
52115                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
52116                                 s4() + '-' + s4() + s4() + s4();
52117                         }
52118                         this.uuid = guid();
52119                         this.Console.addDirective(this.uuid);
52120                         this.Console.showIDs();
52121                     }
52122                     CommandController.prototype.submit = function () {
52123                         var opt = [];
52124                         angular.forEach(this.options, function (option) {
52125                             var obj = {
52126                                 name: option.option,
52127                                 arguments: []
52128                             };
52129                             angular.forEach(option.arg, function (arg) {
52130                                 if (arg.input) {
52131                                     if (typeof arg.input === 'object') {
52132                                         obj.arguments.push(arg.input.name);
52133                                     }
52134                                     else {
52135                                         obj.arguments.push(arg.input);
52136                                     }
52137                                 }
52138                             });
52139                             if (obj.arguments.length > 0) {
52140                                 opt.push(obj);
52141                             }
52142                         });
52143                         var execObj = {
52144                             command: this.name,
52145                             workspace: this.workspace.fileId,
52146                             options: opt
52147                         };
52148                         this.APIEndPoint
52149                             .execute(JSON.stringify(execObj))
52150                             .then(function (result) {
52151                             console.log(result);
52152                         });
52153                     };
52154                     CommandController.prototype.removeMySelf = function (index) {
52155                         this.$scope.$destroy();
52156                         this.Console.removeDirective(this.uuid);
52157                         this.remove()(index, this.list);
52158                         this.Console.showIDs();
52159                     };
52160                     CommandController.prototype.reloadFiles = function () {
52161                         var _this = this;
52162                         var fileId = this.workspace.fileId;
52163                         this.APIEndPoint
52164                             .getFiles(fileId)
52165                             .$promise
52166                             .then(function (result) {
52167                             var status = result.status;
52168                             if (status === 'success') {
52169                                 _this.files = result.info;
52170                             }
52171                             else {
52172                                 console.log(result.message);
52173                             }
52174                         });
52175                     };
52176                     CommandController.prototype.debug = function () {
52177                         var div = angular.element(this.$window.document).find("div");
52178                         var consoleTag;
52179                         var parametersTag;
52180                         angular.forEach(div, function (v) {
52181                             if (v.className === "panel-body console") {
52182                                 consoleTag = v;
52183                             }
52184                             else if (v.className === "row parameters-console") {
52185                                 parametersTag = v;
52186                             }
52187                         });
52188                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
52189                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
52190                         consoleTag.style.height = consoleHeight;
52191                         consoleTag.style.width = consoleWidth;
52192                     };
52193                     CommandController.prototype.help = function () {
52194                         this.APIEndPoint
52195                             .help(this.name)
52196                             .then(function (result) {
52197                             console.log(result);
52198                         });
52199                     };
52200                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
52201                     return CommandController;
52202                 })();
52203                 directives.CommandController = CommandController;
52204             })(directives = app.directives || (app.directives = {}));
52205         })(app || (app = {}));
52206         var app;
52207         (function (app) {
52208             var directives;
52209             (function (directives) {
52210                 var HeaderMenu = (function () {
52211                     function HeaderMenu() {
52212                         this.restrict = 'E';
52213                         this.replace = true;
52214                         this.templateUrl = 'templates/header-menu.html';
52215                         this.controller = 'HeaderMenuController';
52216                         this.controllerAs = 'hmc';
52217                         this.scope = true;
52218                     }
52219                     HeaderMenu.Factory = function () {
52220                         var directive = function () {
52221                             return new HeaderMenu();
52222                         };
52223                         return directive;
52224                     };
52225                     return HeaderMenu;
52226                 })();
52227                 directives.HeaderMenu = HeaderMenu;
52228                 var HeaderMenuController = (function () {
52229                     function HeaderMenuController($state) {
52230                         this.$state = $state;
52231                         this.isExecution = this.$state.current.name === 'execution';
52232                         this.isWorkspace = this.$state.current.name === 'workspace';
52233                         this.isHistory = this.$state.current.name === 'history';
52234                     }
52235                     HeaderMenuController.prototype.transit = function (state) {
52236                         this.$state.go(state);
52237                     };
52238                     HeaderMenuController.$inject = ['$state'];
52239                     return HeaderMenuController;
52240                 })();
52241                 directives.HeaderMenuController = HeaderMenuController;
52242             })(directives = app.directives || (app.directives = {}));
52243         })(app || (app = {}));
52244         var app;
52245         (function (app) {
52246             var directives;
52247             (function (directives) {
52248                 var Option = (function () {
52249                     function Option() {
52250                         this.restrict = 'E';
52251                         this.replace = true;
52252                         this.controller = 'optionController';
52253                         this.bindToController = {
52254                             info: '=',
52255                             files: '='
52256                         };
52257                         this.scope = true;
52258                         this.templateUrl = 'templates/option.html';
52259                         this.controllerAs = 'ctrl';
52260                     }
52261                     Option.Factory = function () {
52262                         var directive = function () {
52263                             return new Option();
52264                         };
52265                         directive.$inject = [];
52266                         return directive;
52267                     };
52268                     return Option;
52269                 })();
52270                 directives.Option = Option;
52271                 var OptionController = (function () {
52272                     function OptionController() {
52273                         var controller = this;
52274                         angular.forEach(controller.info.arg, function (arg) {
52275                             if (arg.initialValue) {
52276                                 if (arg.formType === 'number') {
52277                                     arg.input = parseInt(arg.initialValue);
52278                                 }
52279                                 else {
52280                                     arg.input = arg.initialValue;
52281                                 }
52282                             }
52283                         });
52284                     }
52285                     OptionController.$inject = [];
52286                     return OptionController;
52287                 })();
52288                 directives.OptionController = OptionController;
52289             })(directives = app.directives || (app.directives = {}));
52290         })(app || (app = {}));
52291         var app;
52292         (function (app) {
52293             var directives;
52294             (function (directives) {
52295                 var Directory = (function () {
52296                     function Directory() {
52297                         this.restrict = 'E';
52298                         this.replace = true;
52299                         this.controller = 'directoryController';
52300                         this.controllerAs = 'ctrl';
52301                         this.bindToController = {
52302                             info: '=',
52303                             add: '&',
52304                             list: '=',
52305                             files: '='
52306                         };
52307                         this.templateUrl = 'templates/directory.html';
52308                     }
52309                     Directory.Factory = function () {
52310                         var directive = function () {
52311                             return new Directory();
52312                         };
52313                         return directive;
52314                     };
52315                     return Directory;
52316                 })();
52317                 directives.Directory = Directory;
52318                 var DirectoryController = (function () {
52319                     function DirectoryController(APIEndPoint, $scope) {
52320                         this.APIEndPoint = APIEndPoint;
52321                         this.$scope = $scope;
52322                         var controller = this;
52323                         this.APIEndPoint
52324                             .getFiles(this.info.fileId)
52325                             .$promise
52326                             .then(function (result) {
52327                             if (result.status === 'success') {
52328                                 controller.files = result.info;
52329                                 angular.forEach(result.info, function (file) {
52330                                     if (file.fileType === '0') {
52331                                         var o = file;
52332                                         if (controller.info.path === '/') {
52333                                             o.path = '/' + file.name;
52334                                         }
52335                                         else {
52336                                             o.path = controller.info.path + '/' + file.name;
52337                                         }
52338                                         controller.add()(o, controller.list);
52339                                     }
52340                                 });
52341                             }
52342                             ;
52343                         });
52344                     }
52345                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
52346                     return DirectoryController;
52347                 })();
52348                 directives.DirectoryController = DirectoryController;
52349             })(directives = app.directives || (app.directives = {}));
52350         })(app || (app = {}));
52351         var app;
52352         (function (app) {
52353 <<<<<<< HEAD
52354             var directives;
52355             (function (directives) {
52356                 var Upload = (function () {
52357                     function Upload() {
52358                         this.restrict = 'E';
52359                         this.replace = true;
52360                         this.scope = true;
52361                         this.controller = 'UploadController';
52362                         this.controllerAs = 'ctrl';
52363                         this.bindToController = {
52364                             index: '=',
52365                             name: '=',
52366                             remove: '&',
52367                             list: '='
52368                         };
52369                         this.templateUrl = 'templates/upload.html';
52370                         console.log("templates/upload.html-constructor");
52371                     }
52372                     Upload.Factory = function () {
52373                         var directive = function () {
52374                             return new Upload();
52375                         };
52376                         directive.$inject = [];
52377                         return directive;
52378                     };
52379                     return Upload;
52380                 })();
52381                 directives.Upload = Upload;
52382                 var UploadController = (function () {
52383                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
52384                         this.APIEndPoint = APIEndPoint;
52385                         this.$scope = $scope;
52386                         this.MyModal = MyModal;
52387                         this.WebSocket = WebSocket;
52388                         this.$window = $window;
52389                         this.$rootScope = $rootScope;
52390                         this.Console = Console;
52391                         var controller = this;
52392                         console.log("directive.upload-constructor");
52393                     }
52394                     UploadController.prototype.submit = function () {
52395                         console.log("submit: function not supported¥n");
52396                     };
52397                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
52398                     return UploadController;
52399                 })();
52400                 directives.UploadController = UploadController;
52401             })(directives = app.directives || (app.directives = {}));
52402         })(app || (app = {}));
52403         var app;
52404         (function (app) {
52405 =======
52406 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52407             var controllers;
52408             (function (controllers) {
52409                 var Execution = (function () {
52410                     function Execution(MyModal, $scope) {
52411                         this.MyModal = MyModal;
52412                         this.$scope = $scope;
52413                         this.commandInfoList = [];
52414                     }
52415                     ;
52416                     Execution.prototype.add = function () {
52417                         this.$scope.$broadcast('close');
52418                         var commandInfoList = this.commandInfoList;
52419                         var commandInstance = this.MyModal.selectCommand();
52420                         commandInstance
52421                             .result
52422                             .then(function (command) {
52423                             commandInfoList.push(new app.declares.CommandInfo(command));
52424                         });
52425                     };
52426                     Execution.prototype.open = function () {
52427                         var result = this.MyModal.open('SelectCommand');
52428                         console.log(result);
52429                     };
52430                     Execution.prototype.remove = function (index, list) {
52431                         list.splice(index, 1);
52432                     };
52433                     Execution.prototype.close = function () {
52434                         console.log("close");
52435                     };
52436                     Execution.$inject = ['MyModal', '$scope'];
52437                     return Execution;
52438                 })();
52439                 controllers.Execution = Execution;
52440             })(controllers = app.controllers || (app.controllers = {}));
52441         })(app || (app = {}));
52442         var app;
52443         (function (app) {
52444             var controllers;
52445             (function (controllers) {
52446                 var Workspace = (function () {
52447                     function Workspace($scope, APIEndPoint, MyModal) {
52448                         this.$scope = $scope;
52449                         this.APIEndPoint = APIEndPoint;
52450                         this.MyModal = MyModal;
52451                         this.directoryList = [];
52452                         var controller = this;
52453                         var directoryList = this.directoryList;
52454                         var o = {
52455                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
52456                             name: '',
52457                             parentId: '',
52458                             fileType: '',
52459                             createdAt: '',
52460                             updatedAt: '',
52461                             path: '/'
52462                         };
52463                         directoryList.push(o);
52464                     }
52465                     Workspace.prototype.addDirectory = function (info, directoryList) {
52466                         directoryList.push(info);
52467                     };
52468 <<<<<<< HEAD
52469                     Workspace.prototype.upload = function () {
52470                         this.MyModal.upload();
52471                     };
52472 =======
52473 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52474                     Workspace.prototype.debug = function () {
52475                         this.MyModal.preview();
52476                     };
52477                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
52478                     return Workspace;
52479                 })();
52480                 controllers.Workspace = Workspace;
52481             })(controllers = app.controllers || (app.controllers = {}));
52482         })(app || (app = {}));
52483         var app;
52484         (function (app) {
52485             var controllers;
52486             (function (controllers) {
52487                 var History = (function () {
52488                     function History($scope) {
52489                         this.page = "History";
52490                     }
52491                     History.$inject = ['$scope'];
52492                     return History;
52493                 })();
52494                 controllers.History = History;
52495             })(controllers = app.controllers || (app.controllers = {}));
52496         })(app || (app = {}));
52497         var app;
52498         (function (app) {
52499             var controllers;
52500             (function (controllers) {
52501                 var SelectCommand = (function () {
52502                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
52503                         this.APIEndPoint = APIEndPoint;
52504                         this.$modalInstance = $modalInstance;
52505                         var controller = this;
52506                         this.APIEndPoint
52507                             .getTags()
52508                             .$promise.then(function (result) {
52509                             controller.tags = result.info;
52510                         });
52511                         this.APIEndPoint
52512                             .getCommands()
52513                             .$promise.then(function (result) {
52514                             controller.commands = result.info;
52515                         });
52516                         this.currentTag = 'all';
52517                     }
52518                     SelectCommand.prototype.changeTag = function (tag) {
52519                         this.currentTag = tag;
52520                     };
52521                     SelectCommand.prototype.selectCommand = function (command) {
52522                         this.$modalInstance.close(command);
52523                     };
52524                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
52525                     return SelectCommand;
52526                 })();
52527                 controllers.SelectCommand = SelectCommand;
52528             })(controllers = app.controllers || (app.controllers = {}));
52529         })(app || (app = {}));
52530         var app;
52531         (function (app) {
52532             var controllers;
52533             (function (controllers) {
52534 <<<<<<< HEAD
52535                 var Upload = (function () {
52536                     function Upload($scope, APIEndPoint, $modalInstance) {
52537                         this.APIEndPoint = APIEndPoint;
52538                         this.$modalInstance = $modalInstance;
52539                         var controller = this;
52540                         console.log('controller.upload-controllers');
52541                     }
52542                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
52543                     return Upload;
52544                 })();
52545                 controllers.Upload = Upload;
52546             })(controllers = app.controllers || (app.controllers = {}));
52547         })(app || (app = {}));
52548         var app;
52549         (function (app) {
52550             var controllers;
52551             (function (controllers) {
52552 =======
52553 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52554                 var Preview = (function () {
52555                     function Preview($scope, APIEndPoint, $modalInstance) {
52556                         this.APIEndPoint = APIEndPoint;
52557                         this.$modalInstance = $modalInstance;
52558                         var controller = this;
52559                         console.log('preview');
52560                     }
52561                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
52562                     return Preview;
52563                 })();
52564                 controllers.Preview = Preview;
52565             })(controllers = app.controllers || (app.controllers = {}));
52566         })(app || (app = {}));
52567         var filters;
52568         (function (filters) {
52569             function Tag() {
52570                 return function (commands, tag) {
52571                     var result = [];
52572                     angular.forEach(commands, function (command) {
52573                         var flag = false;
52574                         angular.forEach(command.tags, function (value) {
52575                             if (tag === value)
52576                                 flag = true;
52577                         });
52578                         if (flag)
52579                             result.push(command);
52580                     });
52581                     return result;
52582                 };
52583             }
52584             filters.Tag = Tag;
52585         })(filters || (filters = {}));
52586         var app;
52587         (function (app) {
52588             'use strict';
52589             var appName = 'zephyr';
52590             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
52591             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
52592                 $urlRouterProvider.otherwise('/execution');
52593                 $locationProvider.html5Mode({
52594                     enabled: true,
52595                     requireBase: false
52596                 });
52597                 $stateProvider
52598                     .state('execution', {
52599                     url: '/execution',
52600                     templateUrl: 'templates/execution.html',
52601                     controller: 'executionController',
52602                     controllerAs: 'c'
52603                 })
52604                     .state('workspace', {
52605                     url: '/workspace',
52606                     templateUrl: 'templates/workspace.html',
52607                     controller: 'workspaceController',
52608                     controllerAs: 'c'
52609                 })
52610                     .state('history', {
52611                     url: '/history',
52612                     templateUrl: 'templates/history.html',
52613                     controller: 'historyController',
52614                     controllerAs: 'c'
52615                 });
52616             });
52617             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
52618             app.zephyr.service('MyModal', app.services.MyModal);
52619             app.zephyr.service('WebSocket', app.services.WebSocket);
52620             app.zephyr.service('Console', app.services.Console);
52621             app.zephyr.filter('Tag', filters.Tag);
52622             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
52623             app.zephyr.controller('previewController', app.controllers.Preview);
52624 <<<<<<< HEAD
52625             app.zephyr.controller('uploadController', app.controllers.Upload);
52626 =======
52627 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52628             app.zephyr.controller('executionController', app.controllers.Execution);
52629             app.zephyr.controller('workspaceController', app.controllers.Workspace);
52630             app.zephyr.controller('historyController', app.controllers.History);
52631             app.zephyr.controller('commandController', app.directives.CommandController);
52632             app.zephyr.controller('optionController', app.directives.OptionController);
52633             app.zephyr.controller('directoryController', app.directives.DirectoryController);
52634             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
52635 <<<<<<< HEAD
52636             app.zephyr.controller('uploadController', app.directives.UploadController);
52637 =======
52638 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52639             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
52640             app.zephyr.directive('command', app.directives.Command.Factory());
52641             app.zephyr.directive('option', app.directives.Option.Factory());
52642             app.zephyr.directive('directory', app.directives.Directory.Factory());
52643         })(app || (app = {}));
52644
52645
52646 /***/ },
52647 <<<<<<< HEAD
52648 /* 17 */
52649 =======
52650 /* 15 */
52651 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52652 /***/ function(module, exports) {
52653
52654         var app;
52655         (function (app) {
52656             var declares;
52657             (function (declares) {
52658                 var CommandInfo = (function () {
52659                     function CommandInfo(name) {
52660                         this.name = name;
52661                     }
52662                     return CommandInfo;
52663                 })();
52664                 declares.CommandInfo = CommandInfo;
52665             })(declares = app.declares || (app.declares = {}));
52666         })(app || (app = {}));
52667         var app;
52668         (function (app) {
52669             var services;
52670             (function (services) {
52671                 var APIEndPoint = (function () {
52672                     function APIEndPoint($resource, $http) {
52673                         this.$resource = $resource;
52674                         this.$http = $http;
52675                     }
52676                     APIEndPoint.prototype.resource = function (endPoint, data) {
52677                         var customAction = {
52678                             method: 'GET',
52679                             isArray: false
52680                         };
52681                         var execute = {
52682                             method: 'POST',
52683                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
52684                         };
52685                         return this.$resource(endPoint, {}, { execute: execute });
52686                     };
52687                     APIEndPoint.prototype.getOptionControlFile = function (command) {
52688                         var endPoint = '/api/v1/optionControlFile/' + command;
52689                         return this.resource(endPoint, {}).get();
52690                     };
52691                     APIEndPoint.prototype.getFiles = function (fileId) {
52692                         var endPoint = '/api/v1/workspace';
52693                         if (fileId) {
52694                             endPoint += '/' + fileId;
52695                         }
52696                         return this.resource(endPoint, {}).get();
52697                     };
52698                     APIEndPoint.prototype.getDirectories = function () {
52699                         var endPoint = '/api/v1/all/workspace/directory';
52700                         return this.resource(endPoint, {}).get();
52701                     };
52702                     APIEndPoint.prototype.getTags = function () {
52703                         var endPoint = '/api/v1/tagList';
52704                         return this.resource(endPoint, {}).get();
52705                     };
52706                     APIEndPoint.prototype.getCommands = function () {
52707                         var endPoint = '/api/v1/commandList';
52708                         return this.resource(endPoint, {}).get();
52709                     };
52710                     APIEndPoint.prototype.execute = function (data) {
52711                         var endPoint = '/api/v1/execution';
52712                         var fd = new FormData();
52713                         fd.append('data', data);
52714                         return this.$http.post(endPoint, fd, {
52715                             headers: { 'Content-Type': undefined },
52716                             transformRequest: angular.identity
52717                         });
52718                     };
52719                     APIEndPoint.prototype.debug = function () {
52720                         var endPoint = '/api/v1/debug';
52721                         return this.$http.get(endPoint);
52722                     };
52723 <<<<<<< HEAD
52724                     APIEndPoint.prototype.upload = function () {
52725                         var endPoint = '/api/v1/upload';
52726                         return this.$http.get(endPoint);
52727                     };
52728 =======
52729 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52730                     APIEndPoint.prototype.help = function (command) {
52731                         var endPoint = '/api/v1/help/' + command;
52732                         return this.$http.get(endPoint);
52733                     };
52734                     return APIEndPoint;
52735                 })();
52736                 services.APIEndPoint = APIEndPoint;
52737             })(services = app.services || (app.services = {}));
52738         })(app || (app = {}));
52739         var app;
52740         (function (app) {
52741             var services;
52742             (function (services) {
52743                 var MyModal = (function () {
52744                     function MyModal($uibModal) {
52745                         this.$uibModal = $uibModal;
52746                         this.modalOption = {
52747                             backdrop: true,
52748                             controller: null,
52749                             templateUrl: null,
52750                             size: null
52751                         };
52752                     }
52753                     MyModal.prototype.open = function (modalName) {
52754                         if (modalName === 'SelectCommand') {
52755                             this.modalOption.templateUrl = 'templates/select-command.html';
52756                             this.modalOption.size = 'lg';
52757                         }
52758                         return this.$uibModal.open(this.modalOption);
52759                     };
52760                     MyModal.prototype.selectCommand = function () {
52761                         this.modalOption.templateUrl = 'templates/select-command.html';
52762                         this.modalOption.controller = 'selectCommandController';
52763                         this.modalOption.controllerAs = 'c';
52764                         this.modalOption.size = 'lg';
52765                         return this.$uibModal.open(this.modalOption);
52766                     };
52767                     MyModal.prototype.preview = function () {
52768                         this.modalOption.templateUrl = 'templates/preview.html';
52769                         this.modalOption.controller = 'previewController';
52770                         this.modalOption.controllerAs = 'c';
52771                         this.modalOption.size = 'lg';
52772                         return this.$uibModal.open(this.modalOption);
52773                     };
52774 <<<<<<< HEAD
52775                     MyModal.prototype.upload = function () {
52776                         this.modalOption.templateUrl = 'templates/upload.html';
52777                         this.modalOption.controller = 'uploadController';
52778                         this.modalOption.controllerAs = 'c';
52779                         this.modalOption.size = 'lg';
52780                         return this.$uibModal.open(this.modalOption);
52781                     };
52782 =======
52783 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
52784                     MyModal.$inject = ['$uibModal'];
52785                     return MyModal;
52786                 })();
52787                 services.MyModal = MyModal;
52788             })(services = app.services || (app.services = {}));
52789         })(app || (app = {}));
52790         var app;
52791         (function (app) {
52792             var services;
52793             (function (services) {
52794                 var WebSocket = (function () {
52795                     function WebSocket($rootScope) {
52796                         this.$rootScope = $rootScope;
52797                         this.socket = io.connect();
52798                     }
52799                     WebSocket.prototype.on = function (eventName, callback) {
52800                         var socket = this.socket;
52801                         var rootScope = this.$rootScope;
52802                         socket.on(eventName, function () {
52803                             var args = arguments;
52804                             rootScope.$apply(function () {
52805                                 callback.apply(socket, args);
52806                             });
52807                         });
52808                     };
52809                     WebSocket.prototype.emit = function (eventName, data, callback) {
52810                         var socket = this.socket;
52811                         var rootScope = this.$rootScope;
52812                         this.socket.emit(eventName, data, function () {
52813                             var args = arguments;
52814                             rootScope.$apply(function () {
52815                                 if (callback)
52816                                     callback.apply(socket, args);
52817                             });
52818                         });
52819                     };
52820                     return WebSocket;
52821                 })();
52822                 services.WebSocket = WebSocket;
52823             })(services = app.services || (app.services = {}));
52824         })(app || (app = {}));
52825         var app;
52826         (function (app) {
52827             var services;
52828             (function (services) {
52829                 var Console = (function () {
52830                     function Console(WebSocket, $rootScope) {
52831                         this.WebSocket = WebSocket;
52832                         this.$rootScope = $rootScope;
52833                         this.WebSocket = WebSocket;
52834                         this.$rootScope = $rootScope;
52835                         this.directiveIDs = [];
52836                         var directiveIDs = this.directiveIDs;
52837                         this.WebSocket.on('console', function (d) {
52838                             var id = d.id;
52839                             var message = d.message;
52840                             if (directiveIDs.indexOf(id) > -1) {
52841                                 $rootScope.$emit(id, message);
52842                             }
52843                         });
52844                     }
52845                     Console.prototype.addDirective = function (id) {
52846                         if (!(this.directiveIDs.indexOf(id) > -1)) {
52847                             this.directiveIDs.push(id);
52848                         }
52849                     };
52850                     Console.prototype.removeDirective = function (id) {
52851                         var i = this.directiveIDs.indexOf(id);
52852                         if (i > -1) {
52853                             this.directiveIDs.splice(i, 1);
52854                         }
52855                     };
52856                     Console.prototype.showIDs = function () {
52857                         console.log(this.directiveIDs);
52858                     };
52859                     return Console;
52860                 })();
52861                 services.Console = Console;
52862             })(services = app.services || (app.services = {}));
52863         })(app || (app = {}));
52864         var app;
52865         (function (app) {
52866             var directives;
52867             (function (directives) {
52868                 var Command = (function () {
52869                     function Command() {
52870                         this.restrict = 'E';
52871                         this.replace = true;
52872                         this.scope = true;
52873                         this.controller = 'commandController';
52874                         this.controllerAs = 'ctrl';
52875                         this.bindToController = {
52876                             index: '=',
52877                             name: '=',
52878                             remove: '&',
52879                             list: '='
52880                         };
52881                         this.templateUrl = 'templates/command.html';
52882                     }
52883                     Command.Factory = function () {
52884                         var directive = function () {
52885                             return new Command();
52886                         };
52887                         directive.$inject = [];
52888                         return directive;
52889                     };
52890                     return Command;
52891                 })();
52892                 directives.Command = Command;
52893                 var CommandController = (function () {
52894                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
52895                         this.APIEndPoint = APIEndPoint;
52896                         this.$scope = $scope;
52897                         this.MyModal = MyModal;
52898                         this.WebSocket = WebSocket;
52899                         this.$window = $window;
52900                         this.$rootScope = $rootScope;
52901                         this.Console = Console;
52902                         var controller = this;
52903                         this.APIEndPoint
52904                             .getOptionControlFile(this.name)
52905                             .$promise
52906                             .then(function (result) {
52907                             controller.options = result.info;
52908                         });
52909                         this.APIEndPoint
52910                             .getDirectories()
52911                             .$promise
52912                             .then(function (result) {
52913                             controller.dirs = result.info;
52914                         });
52915                         this.heading = "[" + this.index + "]: dcdFilePrint";
52916                         this.isOpen = true;
52917                         this.$scope.$on('close', function () {
52918                             controller.isOpen = false;
52919                         });
52920                         function guid() {
52921                             function s4() {
52922                                 return Math.floor((1 + Math.random()) * 0x10000)
52923                                     .toString(16)
52924                                     .substring(1);
52925                             }
52926                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
52927                                 s4() + '-' + s4() + s4() + s4();
52928                         }
52929                         this.uuid = guid();
52930                         this.Console.addDirective(this.uuid);
52931                         this.Console.showIDs();
52932                     }
52933                     CommandController.prototype.submit = function () {
52934                         var opt = [];
52935                         angular.forEach(this.options, function (option) {
52936                             var obj = {
52937                                 name: option.option,
52938                                 arguments: []
52939                             };
52940                             angular.forEach(option.arg, function (arg) {
52941                                 if (arg.input) {
52942                                     if (typeof arg.input === 'object') {
52943                                         obj.arguments.push(arg.input.name);
52944                                     }
52945                                     else {
52946                                         obj.arguments.push(arg.input);
52947                                     }
52948                                 }
52949                             });
52950                             if (obj.arguments.length > 0) {
52951                                 opt.push(obj);
52952                             }
52953                         });
52954                         var execObj = {
52955                             command: this.name,
52956                             workspace: this.workspace.fileId,
52957                             options: opt
52958                         };
52959                         this.APIEndPoint
52960                             .execute(JSON.stringify(execObj))
52961                             .then(function (result) {
52962                             console.log(result);
52963                         });
52964                     };
52965                     CommandController.prototype.removeMySelf = function (index) {
52966                         this.$scope.$destroy();
52967                         this.Console.removeDirective(this.uuid);
52968                         this.remove()(index, this.list);
52969                         this.Console.showIDs();
52970                     };
52971                     CommandController.prototype.reloadFiles = function () {
52972                         var _this = this;
52973                         var fileId = this.workspace.fileId;
52974                         this.APIEndPoint
52975                             .getFiles(fileId)
52976                             .$promise
52977                             .then(function (result) {
52978                             var status = result.status;
52979                             if (status === 'success') {
52980                                 _this.files = result.info;
52981                             }
52982                             else {
52983                                 console.log(result.message);
52984                             }
52985                         });
52986                     };
52987                     CommandController.prototype.debug = function () {
52988                         var div = angular.element(this.$window.document).find("div");
52989                         var consoleTag;
52990                         var parametersTag;
52991                         angular.forEach(div, function (v) {
52992                             if (v.className === "panel-body console") {
52993                                 consoleTag = v;
52994                             }
52995                             else if (v.className === "row parameters-console") {
52996                                 parametersTag = v;
52997                             }
52998                         });
52999                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
53000                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
53001                         consoleTag.style.height = consoleHeight;
53002                         consoleTag.style.width = consoleWidth;
53003                     };
53004                     CommandController.prototype.help = function () {
53005                         this.APIEndPoint
53006                             .help(this.name)
53007                             .then(function (result) {
53008                             console.log(result);
53009                         });
53010                     };
53011                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
53012                     return CommandController;
53013                 })();
53014                 directives.CommandController = CommandController;
53015             })(directives = app.directives || (app.directives = {}));
53016         })(app || (app = {}));
53017         var app;
53018         (function (app) {
53019             var directives;
53020             (function (directives) {
53021                 var HeaderMenu = (function () {
53022                     function HeaderMenu() {
53023                         this.restrict = 'E';
53024                         this.replace = true;
53025                         this.templateUrl = 'templates/header-menu.html';
53026                         this.controller = 'HeaderMenuController';
53027                         this.controllerAs = 'hmc';
53028                         this.scope = true;
53029                     }
53030                     HeaderMenu.Factory = function () {
53031                         var directive = function () {
53032                             return new HeaderMenu();
53033                         };
53034                         return directive;
53035                     };
53036                     return HeaderMenu;
53037                 })();
53038                 directives.HeaderMenu = HeaderMenu;
53039                 var HeaderMenuController = (function () {
53040                     function HeaderMenuController($state) {
53041                         this.$state = $state;
53042                         this.isExecution = this.$state.current.name === 'execution';
53043                         this.isWorkspace = this.$state.current.name === 'workspace';
53044                         this.isHistory = this.$state.current.name === 'history';
53045                     }
53046                     HeaderMenuController.prototype.transit = function (state) {
53047                         this.$state.go(state);
53048                     };
53049                     HeaderMenuController.$inject = ['$state'];
53050                     return HeaderMenuController;
53051                 })();
53052                 directives.HeaderMenuController = HeaderMenuController;
53053             })(directives = app.directives || (app.directives = {}));
53054         })(app || (app = {}));
53055         var app;
53056         (function (app) {
53057             var directives;
53058             (function (directives) {
53059                 var Option = (function () {
53060                     function Option() {
53061                         this.restrict = 'E';
53062                         this.replace = true;
53063                         this.controller = 'optionController';
53064                         this.bindToController = {
53065                             info: '=',
53066                             files: '='
53067                         };
53068                         this.scope = true;
53069                         this.templateUrl = 'templates/option.html';
53070                         this.controllerAs = 'ctrl';
53071                     }
53072                     Option.Factory = function () {
53073                         var directive = function () {
53074                             return new Option();
53075                         };
53076                         directive.$inject = [];
53077                         return directive;
53078                     };
53079                     return Option;
53080                 })();
53081                 directives.Option = Option;
53082                 var OptionController = (function () {
53083                     function OptionController() {
53084                         var controller = this;
53085                         angular.forEach(controller.info.arg, function (arg) {
53086                             if (arg.initialValue) {
53087                                 if (arg.formType === 'number') {
53088                                     arg.input = parseInt(arg.initialValue);
53089                                 }
53090                                 else {
53091                                     arg.input = arg.initialValue;
53092                                 }
53093                             }
53094                         });
53095                     }
53096                     OptionController.$inject = [];
53097                     return OptionController;
53098                 })();
53099                 directives.OptionController = OptionController;
53100             })(directives = app.directives || (app.directives = {}));
53101         })(app || (app = {}));
53102         var app;
53103         (function (app) {
53104             var directives;
53105             (function (directives) {
53106                 var Directory = (function () {
53107                     function Directory() {
53108                         this.restrict = 'E';
53109                         this.replace = true;
53110                         this.controller = 'directoryController';
53111                         this.controllerAs = 'ctrl';
53112                         this.bindToController = {
53113                             info: '=',
53114                             add: '&',
53115                             list: '=',
53116                             files: '='
53117                         };
53118                         this.templateUrl = 'templates/directory.html';
53119                     }
53120                     Directory.Factory = function () {
53121                         var directive = function () {
53122                             return new Directory();
53123                         };
53124                         return directive;
53125                     };
53126                     return Directory;
53127                 })();
53128                 directives.Directory = Directory;
53129                 var DirectoryController = (function () {
53130                     function DirectoryController(APIEndPoint, $scope) {
53131                         this.APIEndPoint = APIEndPoint;
53132                         this.$scope = $scope;
53133                         var controller = this;
53134                         this.APIEndPoint
53135                             .getFiles(this.info.fileId)
53136                             .$promise
53137                             .then(function (result) {
53138                             if (result.status === 'success') {
53139                                 controller.files = result.info;
53140                                 angular.forEach(result.info, function (file) {
53141                                     if (file.fileType === '0') {
53142                                         var o = file;
53143                                         if (controller.info.path === '/') {
53144                                             o.path = '/' + file.name;
53145                                         }
53146                                         else {
53147                                             o.path = controller.info.path + '/' + file.name;
53148                                         }
53149                                         controller.add()(o, controller.list);
53150                                     }
53151                                 });
53152                             }
53153                             ;
53154                         });
53155                     }
53156                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
53157                     return DirectoryController;
53158                 })();
53159                 directives.DirectoryController = DirectoryController;
53160             })(directives = app.directives || (app.directives = {}));
53161         })(app || (app = {}));
53162         var app;
53163         (function (app) {
53164 <<<<<<< HEAD
53165             var directives;
53166             (function (directives) {
53167                 var Upload = (function () {
53168                     function Upload() {
53169                         this.restrict = 'E';
53170                         this.replace = true;
53171                         this.scope = true;
53172                         this.controller = 'UploadController';
53173                         this.controllerAs = 'ctrl';
53174                         this.bindToController = {
53175                             index: '=',
53176                             name: '=',
53177                             remove: '&',
53178                             list: '='
53179                         };
53180                         this.templateUrl = 'templates/upload.html';
53181                         console.log("templates/upload.html-constructor");
53182                     }
53183                     Upload.Factory = function () {
53184                         var directive = function () {
53185                             return new Upload();
53186                         };
53187                         directive.$inject = [];
53188                         return directive;
53189                     };
53190                     return Upload;
53191                 })();
53192                 directives.Upload = Upload;
53193                 var UploadController = (function () {
53194                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
53195                         this.APIEndPoint = APIEndPoint;
53196                         this.$scope = $scope;
53197                         this.MyModal = MyModal;
53198                         this.WebSocket = WebSocket;
53199                         this.$window = $window;
53200                         this.$rootScope = $rootScope;
53201                         this.Console = Console;
53202                         var controller = this;
53203                         console.log("directive.upload-constructor");
53204                     }
53205                     UploadController.prototype.submit = function () {
53206                         console.log("submit: function not supported¥n");
53207                     };
53208                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
53209                     return UploadController;
53210                 })();
53211                 directives.UploadController = UploadController;
53212             })(directives = app.directives || (app.directives = {}));
53213         })(app || (app = {}));
53214         var app;
53215         (function (app) {
53216 =======
53217 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53218             var controllers;
53219             (function (controllers) {
53220                 var Execution = (function () {
53221                     function Execution(MyModal, $scope) {
53222                         this.MyModal = MyModal;
53223                         this.$scope = $scope;
53224                         this.commandInfoList = [];
53225                     }
53226                     ;
53227                     Execution.prototype.add = function () {
53228                         this.$scope.$broadcast('close');
53229                         var commandInfoList = this.commandInfoList;
53230                         var commandInstance = this.MyModal.selectCommand();
53231                         commandInstance
53232                             .result
53233                             .then(function (command) {
53234                             commandInfoList.push(new app.declares.CommandInfo(command));
53235                         });
53236                     };
53237                     Execution.prototype.open = function () {
53238                         var result = this.MyModal.open('SelectCommand');
53239                         console.log(result);
53240                     };
53241                     Execution.prototype.remove = function (index, list) {
53242                         list.splice(index, 1);
53243                     };
53244                     Execution.prototype.close = function () {
53245                         console.log("close");
53246                     };
53247                     Execution.$inject = ['MyModal', '$scope'];
53248                     return Execution;
53249                 })();
53250                 controllers.Execution = Execution;
53251             })(controllers = app.controllers || (app.controllers = {}));
53252         })(app || (app = {}));
53253         var app;
53254         (function (app) {
53255             var controllers;
53256             (function (controllers) {
53257                 var Workspace = (function () {
53258                     function Workspace($scope, APIEndPoint, MyModal) {
53259                         this.$scope = $scope;
53260                         this.APIEndPoint = APIEndPoint;
53261                         this.MyModal = MyModal;
53262                         this.directoryList = [];
53263                         var controller = this;
53264                         var directoryList = this.directoryList;
53265                         var o = {
53266                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
53267                             name: '',
53268                             parentId: '',
53269                             fileType: '',
53270                             createdAt: '',
53271                             updatedAt: '',
53272                             path: '/'
53273                         };
53274                         directoryList.push(o);
53275                     }
53276                     Workspace.prototype.addDirectory = function (info, directoryList) {
53277                         directoryList.push(info);
53278                     };
53279 <<<<<<< HEAD
53280                     Workspace.prototype.upload = function () {
53281                         this.MyModal.upload();
53282                     };
53283 =======
53284 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53285                     Workspace.prototype.debug = function () {
53286                         this.MyModal.preview();
53287                     };
53288                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
53289                     return Workspace;
53290                 })();
53291                 controllers.Workspace = Workspace;
53292             })(controllers = app.controllers || (app.controllers = {}));
53293         })(app || (app = {}));
53294         var app;
53295         (function (app) {
53296             var controllers;
53297             (function (controllers) {
53298                 var History = (function () {
53299                     function History($scope) {
53300                         this.page = "History";
53301                     }
53302                     History.$inject = ['$scope'];
53303                     return History;
53304                 })();
53305                 controllers.History = History;
53306             })(controllers = app.controllers || (app.controllers = {}));
53307         })(app || (app = {}));
53308         var app;
53309         (function (app) {
53310             var controllers;
53311             (function (controllers) {
53312                 var SelectCommand = (function () {
53313                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
53314                         this.APIEndPoint = APIEndPoint;
53315                         this.$modalInstance = $modalInstance;
53316                         var controller = this;
53317                         this.APIEndPoint
53318                             .getTags()
53319                             .$promise.then(function (result) {
53320                             controller.tags = result.info;
53321                         });
53322                         this.APIEndPoint
53323                             .getCommands()
53324                             .$promise.then(function (result) {
53325                             controller.commands = result.info;
53326                         });
53327                         this.currentTag = 'all';
53328                     }
53329                     SelectCommand.prototype.changeTag = function (tag) {
53330                         this.currentTag = tag;
53331                     };
53332                     SelectCommand.prototype.selectCommand = function (command) {
53333                         this.$modalInstance.close(command);
53334                     };
53335                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
53336                     return SelectCommand;
53337                 })();
53338                 controllers.SelectCommand = SelectCommand;
53339             })(controllers = app.controllers || (app.controllers = {}));
53340         })(app || (app = {}));
53341         var app;
53342         (function (app) {
53343             var controllers;
53344             (function (controllers) {
53345 <<<<<<< HEAD
53346                 var Upload = (function () {
53347                     function Upload($scope, APIEndPoint, $modalInstance) {
53348                         this.APIEndPoint = APIEndPoint;
53349                         this.$modalInstance = $modalInstance;
53350                         var controller = this;
53351                         console.log('controller.upload-controllers');
53352                     }
53353                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
53354                     return Upload;
53355                 })();
53356                 controllers.Upload = Upload;
53357             })(controllers = app.controllers || (app.controllers = {}));
53358         })(app || (app = {}));
53359         var app;
53360         (function (app) {
53361             var controllers;
53362             (function (controllers) {
53363 =======
53364 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53365                 var Preview = (function () {
53366                     function Preview($scope, APIEndPoint, $modalInstance) {
53367                         this.APIEndPoint = APIEndPoint;
53368                         this.$modalInstance = $modalInstance;
53369                         var controller = this;
53370                         console.log('preview');
53371                     }
53372                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
53373                     return Preview;
53374                 })();
53375                 controllers.Preview = Preview;
53376             })(controllers = app.controllers || (app.controllers = {}));
53377         })(app || (app = {}));
53378         var filters;
53379         (function (filters) {
53380             function Tag() {
53381                 return function (commands, tag) {
53382                     var result = [];
53383                     angular.forEach(commands, function (command) {
53384                         var flag = false;
53385                         angular.forEach(command.tags, function (value) {
53386                             if (tag === value)
53387                                 flag = true;
53388                         });
53389                         if (flag)
53390                             result.push(command);
53391                     });
53392                     return result;
53393                 };
53394             }
53395             filters.Tag = Tag;
53396         })(filters || (filters = {}));
53397         var app;
53398         (function (app) {
53399             'use strict';
53400             var appName = 'zephyr';
53401             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
53402             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
53403                 $urlRouterProvider.otherwise('/execution');
53404                 $locationProvider.html5Mode({
53405                     enabled: true,
53406                     requireBase: false
53407                 });
53408                 $stateProvider
53409                     .state('execution', {
53410                     url: '/execution',
53411                     templateUrl: 'templates/execution.html',
53412                     controller: 'executionController',
53413                     controllerAs: 'c'
53414                 })
53415                     .state('workspace', {
53416                     url: '/workspace',
53417                     templateUrl: 'templates/workspace.html',
53418                     controller: 'workspaceController',
53419                     controllerAs: 'c'
53420                 })
53421                     .state('history', {
53422                     url: '/history',
53423                     templateUrl: 'templates/history.html',
53424                     controller: 'historyController',
53425                     controllerAs: 'c'
53426                 });
53427             });
53428             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
53429             app.zephyr.service('MyModal', app.services.MyModal);
53430             app.zephyr.service('WebSocket', app.services.WebSocket);
53431             app.zephyr.service('Console', app.services.Console);
53432             app.zephyr.filter('Tag', filters.Tag);
53433             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
53434             app.zephyr.controller('previewController', app.controllers.Preview);
53435 <<<<<<< HEAD
53436             app.zephyr.controller('uploadController', app.controllers.Upload);
53437 =======
53438 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53439             app.zephyr.controller('executionController', app.controllers.Execution);
53440             app.zephyr.controller('workspaceController', app.controllers.Workspace);
53441             app.zephyr.controller('historyController', app.controllers.History);
53442             app.zephyr.controller('commandController', app.directives.CommandController);
53443             app.zephyr.controller('optionController', app.directives.OptionController);
53444             app.zephyr.controller('directoryController', app.directives.DirectoryController);
53445             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
53446 <<<<<<< HEAD
53447             app.zephyr.controller('uploadController', app.directives.UploadController);
53448 =======
53449 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53450             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
53451             app.zephyr.directive('command', app.directives.Command.Factory());
53452             app.zephyr.directive('option', app.directives.Option.Factory());
53453             app.zephyr.directive('directory', app.directives.Directory.Factory());
53454         })(app || (app = {}));
53455
53456
53457 /***/ },
53458 <<<<<<< HEAD
53459 /* 18 */
53460 =======
53461 /* 16 */
53462 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53463 /***/ function(module, exports) {
53464
53465         var app;
53466         (function (app) {
53467             var declares;
53468             (function (declares) {
53469                 var CommandInfo = (function () {
53470                     function CommandInfo(name) {
53471                         this.name = name;
53472                     }
53473                     return CommandInfo;
53474                 })();
53475                 declares.CommandInfo = CommandInfo;
53476             })(declares = app.declares || (app.declares = {}));
53477         })(app || (app = {}));
53478         var app;
53479         (function (app) {
53480             var services;
53481             (function (services) {
53482                 var APIEndPoint = (function () {
53483                     function APIEndPoint($resource, $http) {
53484                         this.$resource = $resource;
53485                         this.$http = $http;
53486                     }
53487                     APIEndPoint.prototype.resource = function (endPoint, data) {
53488                         var customAction = {
53489                             method: 'GET',
53490                             isArray: false
53491                         };
53492                         var execute = {
53493                             method: 'POST',
53494                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
53495                         };
53496                         return this.$resource(endPoint, {}, { execute: execute });
53497                     };
53498                     APIEndPoint.prototype.getOptionControlFile = function (command) {
53499                         var endPoint = '/api/v1/optionControlFile/' + command;
53500                         return this.resource(endPoint, {}).get();
53501                     };
53502                     APIEndPoint.prototype.getFiles = function (fileId) {
53503                         var endPoint = '/api/v1/workspace';
53504                         if (fileId) {
53505                             endPoint += '/' + fileId;
53506                         }
53507                         return this.resource(endPoint, {}).get();
53508                     };
53509                     APIEndPoint.prototype.getDirectories = function () {
53510                         var endPoint = '/api/v1/all/workspace/directory';
53511                         return this.resource(endPoint, {}).get();
53512                     };
53513                     APIEndPoint.prototype.getTags = function () {
53514                         var endPoint = '/api/v1/tagList';
53515                         return this.resource(endPoint, {}).get();
53516                     };
53517                     APIEndPoint.prototype.getCommands = function () {
53518                         var endPoint = '/api/v1/commandList';
53519                         return this.resource(endPoint, {}).get();
53520                     };
53521                     APIEndPoint.prototype.execute = function (data) {
53522                         var endPoint = '/api/v1/execution';
53523                         var fd = new FormData();
53524                         fd.append('data', data);
53525                         return this.$http.post(endPoint, fd, {
53526                             headers: { 'Content-Type': undefined },
53527                             transformRequest: angular.identity
53528                         });
53529                     };
53530                     APIEndPoint.prototype.debug = function () {
53531                         var endPoint = '/api/v1/debug';
53532                         return this.$http.get(endPoint);
53533                     };
53534 <<<<<<< HEAD
53535                     APIEndPoint.prototype.upload = function () {
53536                         var endPoint = '/api/v1/upload';
53537                         return this.$http.get(endPoint);
53538                     };
53539 =======
53540 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53541                     APIEndPoint.prototype.help = function (command) {
53542                         var endPoint = '/api/v1/help/' + command;
53543                         return this.$http.get(endPoint);
53544                     };
53545                     return APIEndPoint;
53546                 })();
53547                 services.APIEndPoint = APIEndPoint;
53548             })(services = app.services || (app.services = {}));
53549         })(app || (app = {}));
53550         var app;
53551         (function (app) {
53552             var services;
53553             (function (services) {
53554                 var MyModal = (function () {
53555                     function MyModal($uibModal) {
53556                         this.$uibModal = $uibModal;
53557                         this.modalOption = {
53558                             backdrop: true,
53559                             controller: null,
53560                             templateUrl: null,
53561                             size: null
53562                         };
53563                     }
53564                     MyModal.prototype.open = function (modalName) {
53565                         if (modalName === 'SelectCommand') {
53566                             this.modalOption.templateUrl = 'templates/select-command.html';
53567                             this.modalOption.size = 'lg';
53568                         }
53569                         return this.$uibModal.open(this.modalOption);
53570                     };
53571                     MyModal.prototype.selectCommand = function () {
53572                         this.modalOption.templateUrl = 'templates/select-command.html';
53573                         this.modalOption.controller = 'selectCommandController';
53574                         this.modalOption.controllerAs = 'c';
53575                         this.modalOption.size = 'lg';
53576                         return this.$uibModal.open(this.modalOption);
53577                     };
53578                     MyModal.prototype.preview = function () {
53579                         this.modalOption.templateUrl = 'templates/preview.html';
53580                         this.modalOption.controller = 'previewController';
53581                         this.modalOption.controllerAs = 'c';
53582                         this.modalOption.size = 'lg';
53583                         return this.$uibModal.open(this.modalOption);
53584                     };
53585 <<<<<<< HEAD
53586                     MyModal.prototype.upload = function () {
53587                         this.modalOption.templateUrl = 'templates/upload.html';
53588                         this.modalOption.controller = 'uploadController';
53589                         this.modalOption.controllerAs = 'c';
53590                         this.modalOption.size = 'lg';
53591                         return this.$uibModal.open(this.modalOption);
53592                     };
53593 =======
53594 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
53595                     MyModal.$inject = ['$uibModal'];
53596                     return MyModal;
53597                 })();
53598                 services.MyModal = MyModal;
53599             })(services = app.services || (app.services = {}));
53600         })(app || (app = {}));
53601         var app;
53602         (function (app) {
53603             var services;
53604             (function (services) {
53605                 var WebSocket = (function () {
53606                     function WebSocket($rootScope) {
53607                         this.$rootScope = $rootScope;
53608                         this.socket = io.connect();
53609                     }
53610                     WebSocket.prototype.on = function (eventName, callback) {
53611                         var socket = this.socket;
53612                         var rootScope = this.$rootScope;
53613                         socket.on(eventName, function () {
53614                             var args = arguments;
53615                             rootScope.$apply(function () {
53616                                 callback.apply(socket, args);
53617                             });
53618                         });
53619                     };
53620                     WebSocket.prototype.emit = function (eventName, data, callback) {
53621                         var socket = this.socket;
53622                         var rootScope = this.$rootScope;
53623                         this.socket.emit(eventName, data, function () {
53624                             var args = arguments;
53625                             rootScope.$apply(function () {
53626                                 if (callback)
53627                                     callback.apply(socket, args);
53628                             });
53629                         });
53630                     };
53631                     return WebSocket;
53632                 })();
53633                 services.WebSocket = WebSocket;
53634             })(services = app.services || (app.services = {}));
53635         })(app || (app = {}));
53636         var app;
53637         (function (app) {
53638             var services;
53639             (function (services) {
53640                 var Console = (function () {
53641                     function Console(WebSocket, $rootScope) {
53642                         this.WebSocket = WebSocket;
53643                         this.$rootScope = $rootScope;
53644                         this.WebSocket = WebSocket;
53645                         this.$rootScope = $rootScope;
53646                         this.directiveIDs = [];
53647                         var directiveIDs = this.directiveIDs;
53648                         this.WebSocket.on('console', function (d) {
53649                             var id = d.id;
53650                             var message = d.message;
53651                             if (directiveIDs.indexOf(id) > -1) {
53652                                 $rootScope.$emit(id, message);
53653                             }
53654                         });
53655                     }
53656                     Console.prototype.addDirective = function (id) {
53657                         if (!(this.directiveIDs.indexOf(id) > -1)) {
53658                             this.directiveIDs.push(id);
53659                         }
53660                     };
53661                     Console.prototype.removeDirective = function (id) {
53662                         var i = this.directiveIDs.indexOf(id);
53663                         if (i > -1) {
53664                             this.directiveIDs.splice(i, 1);
53665                         }
53666                     };
53667                     Console.prototype.showIDs = function () {
53668                         console.log(this.directiveIDs);
53669                     };
53670                     return Console;
53671                 })();
53672                 services.Console = Console;
53673             })(services = app.services || (app.services = {}));
53674         })(app || (app = {}));
53675         var app;
53676         (function (app) {
53677             var directives;
53678             (function (directives) {
53679                 var Command = (function () {
53680                     function Command() {
53681                         this.restrict = 'E';
53682                         this.replace = true;
53683                         this.scope = true;
53684                         this.controller = 'commandController';
53685                         this.controllerAs = 'ctrl';
53686                         this.bindToController = {
53687                             index: '=',
53688                             name: '=',
53689                             remove: '&',
53690                             list: '='
53691                         };
53692                         this.templateUrl = 'templates/command.html';
53693                     }
53694                     Command.Factory = function () {
53695                         var directive = function () {
53696                             return new Command();
53697                         };
53698                         directive.$inject = [];
53699                         return directive;
53700                     };
53701                     return Command;
53702                 })();
53703                 directives.Command = Command;
53704                 var CommandController = (function () {
53705                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
53706                         this.APIEndPoint = APIEndPoint;
53707                         this.$scope = $scope;
53708                         this.MyModal = MyModal;
53709                         this.WebSocket = WebSocket;
53710                         this.$window = $window;
53711                         this.$rootScope = $rootScope;
53712                         this.Console = Console;
53713                         var controller = this;
53714                         this.APIEndPoint
53715                             .getOptionControlFile(this.name)
53716                             .$promise
53717                             .then(function (result) {
53718                             controller.options = result.info;
53719                         });
53720                         this.APIEndPoint
53721                             .getDirectories()
53722                             .$promise
53723                             .then(function (result) {
53724                             controller.dirs = result.info;
53725                         });
53726                         this.heading = "[" + this.index + "]: dcdFilePrint";
53727                         this.isOpen = true;
53728                         this.$scope.$on('close', function () {
53729                             controller.isOpen = false;
53730                         });
53731                         function guid() {
53732                             function s4() {
53733                                 return Math.floor((1 + Math.random()) * 0x10000)
53734                                     .toString(16)
53735                                     .substring(1);
53736                             }
53737                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
53738                                 s4() + '-' + s4() + s4() + s4();
53739                         }
53740                         this.uuid = guid();
53741                         this.Console.addDirective(this.uuid);
53742                         this.Console.showIDs();
53743                     }
53744                     CommandController.prototype.submit = function () {
53745                         var opt = [];
53746                         angular.forEach(this.options, function (option) {
53747                             var obj = {
53748                                 name: option.option,
53749                                 arguments: []
53750                             };
53751                             angular.forEach(option.arg, function (arg) {
53752                                 if (arg.input) {
53753                                     if (typeof arg.input === 'object') {
53754                                         obj.arguments.push(arg.input.name);
53755                                     }
53756                                     else {
53757                                         obj.arguments.push(arg.input);
53758                                     }
53759                                 }
53760                             });
53761                             if (obj.arguments.length > 0) {
53762                                 opt.push(obj);
53763                             }
53764                         });
53765                         var execObj = {
53766                             command: this.name,
53767                             workspace: this.workspace.fileId,
53768                             options: opt
53769                         };
53770                         this.APIEndPoint
53771                             .execute(JSON.stringify(execObj))
53772                             .then(function (result) {
53773                             console.log(result);
53774                         });
53775                     };
53776                     CommandController.prototype.removeMySelf = function (index) {
53777                         this.$scope.$destroy();
53778                         this.Console.removeDirective(this.uuid);
53779                         this.remove()(index, this.list);
53780                         this.Console.showIDs();
53781                     };
53782                     CommandController.prototype.reloadFiles = function () {
53783                         var _this = this;
53784                         var fileId = this.workspace.fileId;
53785                         this.APIEndPoint
53786                             .getFiles(fileId)
53787                             .$promise
53788                             .then(function (result) {
53789                             var status = result.status;
53790                             if (status === 'success') {
53791                                 _this.files = result.info;
53792                             }
53793                             else {
53794                                 console.log(result.message);
53795                             }
53796                         });
53797                     };
53798                     CommandController.prototype.debug = function () {
53799                         var div = angular.element(this.$window.document).find("div");
53800                         var consoleTag;
53801                         var parametersTag;
53802                         angular.forEach(div, function (v) {
53803                             if (v.className === "panel-body console") {
53804                                 consoleTag = v;
53805                             }
53806                             else if (v.className === "row parameters-console") {
53807                                 parametersTag = v;
53808                             }
53809                         });
53810                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
53811                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
53812                         consoleTag.style.height = consoleHeight;
53813                         consoleTag.style.width = consoleWidth;
53814                     };
53815                     CommandController.prototype.help = function () {
53816                         this.APIEndPoint
53817                             .help(this.name)
53818                             .then(function (result) {
53819                             console.log(result);
53820                         });
53821                     };
53822                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
53823                     return CommandController;
53824                 })();
53825                 directives.CommandController = CommandController;
53826             })(directives = app.directives || (app.directives = {}));
53827         })(app || (app = {}));
53828         var app;
53829         (function (app) {
53830             var directives;
53831             (function (directives) {
53832                 var HeaderMenu = (function () {
53833                     function HeaderMenu() {
53834                         this.restrict = 'E';
53835                         this.replace = true;
53836                         this.templateUrl = 'templates/header-menu.html';
53837                         this.controller = 'HeaderMenuController';
53838                         this.controllerAs = 'hmc';
53839                         this.scope = true;
53840                     }
53841                     HeaderMenu.Factory = function () {
53842                         var directive = function () {
53843                             return new HeaderMenu();
53844                         };
53845                         return directive;
53846                     };
53847                     return HeaderMenu;
53848                 })();
53849                 directives.HeaderMenu = HeaderMenu;
53850                 var HeaderMenuController = (function () {
53851                     function HeaderMenuController($state) {
53852                         this.$state = $state;
53853                         this.isExecution = this.$state.current.name === 'execution';
53854                         this.isWorkspace = this.$state.current.name === 'workspace';
53855                         this.isHistory = this.$state.current.name === 'history';
53856                     }
53857                     HeaderMenuController.prototype.transit = function (state) {
53858                         this.$state.go(state);
53859                     };
53860                     HeaderMenuController.$inject = ['$state'];
53861                     return HeaderMenuController;
53862                 })();
53863                 directives.HeaderMenuController = HeaderMenuController;
53864             })(directives = app.directives || (app.directives = {}));
53865         })(app || (app = {}));
53866         var app;
53867         (function (app) {
53868             var directives;
53869             (function (directives) {
53870                 var Option = (function () {
53871                     function Option() {
53872                         this.restrict = 'E';
53873                         this.replace = true;
53874                         this.controller = 'optionController';
53875                         this.bindToController = {
53876                             info: '=',
53877                             files: '='
53878                         };
53879                         this.scope = true;
53880                         this.templateUrl = 'templates/option.html';
53881                         this.controllerAs = 'ctrl';
53882                     }
53883                     Option.Factory = function () {
53884                         var directive = function () {
53885                             return new Option();
53886                         };
53887                         directive.$inject = [];
53888                         return directive;
53889                     };
53890                     return Option;
53891                 })();
53892                 directives.Option = Option;
53893                 var OptionController = (function () {
53894                     function OptionController() {
53895                         var controller = this;
53896                         angular.forEach(controller.info.arg, function (arg) {
53897                             if (arg.initialValue) {
53898                                 if (arg.formType === 'number') {
53899                                     arg.input = parseInt(arg.initialValue);
53900                                 }
53901                                 else {
53902                                     arg.input = arg.initialValue;
53903                                 }
53904                             }
53905                         });
53906                     }
53907                     OptionController.$inject = [];
53908                     return OptionController;
53909                 })();
53910                 directives.OptionController = OptionController;
53911             })(directives = app.directives || (app.directives = {}));
53912         })(app || (app = {}));
53913         var app;
53914         (function (app) {
53915             var directives;
53916             (function (directives) {
53917                 var Directory = (function () {
53918                     function Directory() {
53919                         this.restrict = 'E';
53920                         this.replace = true;
53921                         this.controller = 'directoryController';
53922                         this.controllerAs = 'ctrl';
53923                         this.bindToController = {
53924                             info: '=',
53925                             add: '&',
53926                             list: '=',
53927                             files: '='
53928                         };
53929                         this.templateUrl = 'templates/directory.html';
53930                     }
53931                     Directory.Factory = function () {
53932                         var directive = function () {
53933                             return new Directory();
53934                         };
53935                         return directive;
53936                     };
53937                     return Directory;
53938                 })();
53939                 directives.Directory = Directory;
53940                 var DirectoryController = (function () {
53941                     function DirectoryController(APIEndPoint, $scope) {
53942                         this.APIEndPoint = APIEndPoint;
53943                         this.$scope = $scope;
53944                         var controller = this;
53945                         this.APIEndPoint
53946                             .getFiles(this.info.fileId)
53947                             .$promise
53948                             .then(function (result) {
53949                             if (result.status === 'success') {
53950                                 controller.files = result.info;
53951                                 angular.forEach(result.info, function (file) {
53952                                     if (file.fileType === '0') {
53953                                         var o = file;
53954                                         if (controller.info.path === '/') {
53955                                             o.path = '/' + file.name;
53956                                         }
53957                                         else {
53958                                             o.path = controller.info.path + '/' + file.name;
53959                                         }
53960                                         controller.add()(o, controller.list);
53961                                     }
53962                                 });
53963                             }
53964                             ;
53965                         });
53966                     }
53967                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
53968                     return DirectoryController;
53969                 })();
53970                 directives.DirectoryController = DirectoryController;
53971             })(directives = app.directives || (app.directives = {}));
53972         })(app || (app = {}));
53973         var app;
53974         (function (app) {
53975 <<<<<<< HEAD
53976             var directives;
53977             (function (directives) {
53978                 var Upload = (function () {
53979                     function Upload() {
53980                         this.restrict = 'E';
53981                         this.replace = true;
53982                         this.scope = true;
53983                         this.controller = 'UploadController';
53984                         this.controllerAs = 'ctrl';
53985                         this.bindToController = {
53986                             index: '=',
53987                             name: '=',
53988                             remove: '&',
53989                             list: '='
53990                         };
53991                         this.templateUrl = 'templates/upload.html';
53992                         console.log("templates/upload.html-constructor");
53993                     }
53994                     Upload.Factory = function () {
53995                         var directive = function () {
53996                             return new Upload();
53997                         };
53998                         directive.$inject = [];
53999                         return directive;
54000                     };
54001                     return Upload;
54002                 })();
54003                 directives.Upload = Upload;
54004                 var UploadController = (function () {
54005                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
54006                         this.APIEndPoint = APIEndPoint;
54007                         this.$scope = $scope;
54008                         this.MyModal = MyModal;
54009                         this.WebSocket = WebSocket;
54010                         this.$window = $window;
54011                         this.$rootScope = $rootScope;
54012                         this.Console = Console;
54013                         var controller = this;
54014                         console.log("directive.upload-constructor");
54015                     }
54016                     UploadController.prototype.submit = function () {
54017                         console.log("submit: function not supported¥n");
54018                     };
54019                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
54020                     return UploadController;
54021                 })();
54022                 directives.UploadController = UploadController;
54023             })(directives = app.directives || (app.directives = {}));
54024         })(app || (app = {}));
54025         var app;
54026         (function (app) {
54027 =======
54028 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54029             var controllers;
54030             (function (controllers) {
54031                 var Execution = (function () {
54032                     function Execution(MyModal, $scope) {
54033                         this.MyModal = MyModal;
54034                         this.$scope = $scope;
54035                         this.commandInfoList = [];
54036                     }
54037                     ;
54038                     Execution.prototype.add = function () {
54039                         this.$scope.$broadcast('close');
54040                         var commandInfoList = this.commandInfoList;
54041                         var commandInstance = this.MyModal.selectCommand();
54042                         commandInstance
54043                             .result
54044                             .then(function (command) {
54045                             commandInfoList.push(new app.declares.CommandInfo(command));
54046                         });
54047                     };
54048                     Execution.prototype.open = function () {
54049                         var result = this.MyModal.open('SelectCommand');
54050                         console.log(result);
54051                     };
54052                     Execution.prototype.remove = function (index, list) {
54053                         list.splice(index, 1);
54054                     };
54055                     Execution.prototype.close = function () {
54056                         console.log("close");
54057                     };
54058                     Execution.$inject = ['MyModal', '$scope'];
54059                     return Execution;
54060                 })();
54061                 controllers.Execution = Execution;
54062             })(controllers = app.controllers || (app.controllers = {}));
54063         })(app || (app = {}));
54064         var app;
54065         (function (app) {
54066             var controllers;
54067             (function (controllers) {
54068                 var Workspace = (function () {
54069                     function Workspace($scope, APIEndPoint, MyModal) {
54070                         this.$scope = $scope;
54071                         this.APIEndPoint = APIEndPoint;
54072                         this.MyModal = MyModal;
54073                         this.directoryList = [];
54074                         var controller = this;
54075                         var directoryList = this.directoryList;
54076                         var o = {
54077                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
54078                             name: '',
54079                             parentId: '',
54080                             fileType: '',
54081                             createdAt: '',
54082                             updatedAt: '',
54083                             path: '/'
54084                         };
54085                         directoryList.push(o);
54086                     }
54087                     Workspace.prototype.addDirectory = function (info, directoryList) {
54088                         directoryList.push(info);
54089                     };
54090 <<<<<<< HEAD
54091                     Workspace.prototype.upload = function () {
54092                         this.MyModal.upload();
54093                     };
54094 =======
54095 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54096                     Workspace.prototype.debug = function () {
54097                         this.MyModal.preview();
54098                     };
54099                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
54100                     return Workspace;
54101                 })();
54102                 controllers.Workspace = Workspace;
54103             })(controllers = app.controllers || (app.controllers = {}));
54104         })(app || (app = {}));
54105         var app;
54106         (function (app) {
54107             var controllers;
54108             (function (controllers) {
54109                 var History = (function () {
54110                     function History($scope) {
54111                         this.page = "History";
54112                     }
54113                     History.$inject = ['$scope'];
54114                     return History;
54115                 })();
54116                 controllers.History = History;
54117             })(controllers = app.controllers || (app.controllers = {}));
54118         })(app || (app = {}));
54119         var app;
54120         (function (app) {
54121             var controllers;
54122             (function (controllers) {
54123                 var SelectCommand = (function () {
54124                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
54125                         this.APIEndPoint = APIEndPoint;
54126                         this.$modalInstance = $modalInstance;
54127                         var controller = this;
54128                         this.APIEndPoint
54129                             .getTags()
54130                             .$promise.then(function (result) {
54131                             controller.tags = result.info;
54132                         });
54133                         this.APIEndPoint
54134                             .getCommands()
54135                             .$promise.then(function (result) {
54136                             controller.commands = result.info;
54137                         });
54138                         this.currentTag = 'all';
54139                     }
54140                     SelectCommand.prototype.changeTag = function (tag) {
54141                         this.currentTag = tag;
54142                     };
54143                     SelectCommand.prototype.selectCommand = function (command) {
54144                         this.$modalInstance.close(command);
54145                     };
54146                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
54147                     return SelectCommand;
54148                 })();
54149                 controllers.SelectCommand = SelectCommand;
54150             })(controllers = app.controllers || (app.controllers = {}));
54151         })(app || (app = {}));
54152         var app;
54153         (function (app) {
54154             var controllers;
54155             (function (controllers) {
54156 <<<<<<< HEAD
54157                 var Upload = (function () {
54158                     function Upload($scope, APIEndPoint, $modalInstance) {
54159                         this.APIEndPoint = APIEndPoint;
54160                         this.$modalInstance = $modalInstance;
54161                         var controller = this;
54162                         console.log('controller.upload-controllers');
54163                     }
54164                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
54165                     return Upload;
54166                 })();
54167                 controllers.Upload = Upload;
54168             })(controllers = app.controllers || (app.controllers = {}));
54169         })(app || (app = {}));
54170         var app;
54171         (function (app) {
54172             var controllers;
54173             (function (controllers) {
54174 =======
54175 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54176                 var Preview = (function () {
54177                     function Preview($scope, APIEndPoint, $modalInstance) {
54178                         this.APIEndPoint = APIEndPoint;
54179                         this.$modalInstance = $modalInstance;
54180                         var controller = this;
54181                         console.log('preview');
54182                     }
54183                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
54184                     return Preview;
54185                 })();
54186                 controllers.Preview = Preview;
54187             })(controllers = app.controllers || (app.controllers = {}));
54188         })(app || (app = {}));
54189         var filters;
54190         (function (filters) {
54191             function Tag() {
54192                 return function (commands, tag) {
54193                     var result = [];
54194                     angular.forEach(commands, function (command) {
54195                         var flag = false;
54196                         angular.forEach(command.tags, function (value) {
54197                             if (tag === value)
54198                                 flag = true;
54199                         });
54200                         if (flag)
54201                             result.push(command);
54202                     });
54203                     return result;
54204                 };
54205             }
54206             filters.Tag = Tag;
54207         })(filters || (filters = {}));
54208         var app;
54209         (function (app) {
54210             'use strict';
54211             var appName = 'zephyr';
54212             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
54213             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
54214                 $urlRouterProvider.otherwise('/execution');
54215                 $locationProvider.html5Mode({
54216                     enabled: true,
54217                     requireBase: false
54218                 });
54219                 $stateProvider
54220                     .state('execution', {
54221                     url: '/execution',
54222                     templateUrl: 'templates/execution.html',
54223                     controller: 'executionController',
54224                     controllerAs: 'c'
54225                 })
54226                     .state('workspace', {
54227                     url: '/workspace',
54228                     templateUrl: 'templates/workspace.html',
54229                     controller: 'workspaceController',
54230                     controllerAs: 'c'
54231                 })
54232                     .state('history', {
54233                     url: '/history',
54234                     templateUrl: 'templates/history.html',
54235                     controller: 'historyController',
54236                     controllerAs: 'c'
54237                 });
54238             });
54239             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
54240             app.zephyr.service('MyModal', app.services.MyModal);
54241             app.zephyr.service('WebSocket', app.services.WebSocket);
54242             app.zephyr.service('Console', app.services.Console);
54243             app.zephyr.filter('Tag', filters.Tag);
54244             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
54245             app.zephyr.controller('previewController', app.controllers.Preview);
54246 <<<<<<< HEAD
54247             app.zephyr.controller('uploadController', app.controllers.Upload);
54248 =======
54249 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54250             app.zephyr.controller('executionController', app.controllers.Execution);
54251             app.zephyr.controller('workspaceController', app.controllers.Workspace);
54252             app.zephyr.controller('historyController', app.controllers.History);
54253             app.zephyr.controller('commandController', app.directives.CommandController);
54254             app.zephyr.controller('optionController', app.directives.OptionController);
54255             app.zephyr.controller('directoryController', app.directives.DirectoryController);
54256             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
54257 <<<<<<< HEAD
54258             app.zephyr.controller('uploadController', app.directives.UploadController);
54259 =======
54260 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54261             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
54262             app.zephyr.directive('command', app.directives.Command.Factory());
54263             app.zephyr.directive('option', app.directives.Option.Factory());
54264             app.zephyr.directive('directory', app.directives.Directory.Factory());
54265         })(app || (app = {}));
54266
54267
54268 /***/ },
54269 <<<<<<< HEAD
54270 /* 19 */
54271 =======
54272 /* 17 */
54273 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54274 /***/ function(module, exports) {
54275
54276         var app;
54277         (function (app) {
54278             var declares;
54279             (function (declares) {
54280                 var CommandInfo = (function () {
54281                     function CommandInfo(name) {
54282                         this.name = name;
54283                     }
54284                     return CommandInfo;
54285                 })();
54286                 declares.CommandInfo = CommandInfo;
54287             })(declares = app.declares || (app.declares = {}));
54288         })(app || (app = {}));
54289         var app;
54290         (function (app) {
54291             var services;
54292             (function (services) {
54293                 var APIEndPoint = (function () {
54294                     function APIEndPoint($resource, $http) {
54295                         this.$resource = $resource;
54296                         this.$http = $http;
54297                     }
54298                     APIEndPoint.prototype.resource = function (endPoint, data) {
54299                         var customAction = {
54300                             method: 'GET',
54301                             isArray: false
54302                         };
54303                         var execute = {
54304                             method: 'POST',
54305                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
54306                         };
54307                         return this.$resource(endPoint, {}, { execute: execute });
54308                     };
54309                     APIEndPoint.prototype.getOptionControlFile = function (command) {
54310                         var endPoint = '/api/v1/optionControlFile/' + command;
54311                         return this.resource(endPoint, {}).get();
54312                     };
54313                     APIEndPoint.prototype.getFiles = function (fileId) {
54314                         var endPoint = '/api/v1/workspace';
54315                         if (fileId) {
54316                             endPoint += '/' + fileId;
54317                         }
54318                         return this.resource(endPoint, {}).get();
54319                     };
54320                     APIEndPoint.prototype.getDirectories = function () {
54321                         var endPoint = '/api/v1/all/workspace/directory';
54322                         return this.resource(endPoint, {}).get();
54323                     };
54324                     APIEndPoint.prototype.getTags = function () {
54325                         var endPoint = '/api/v1/tagList';
54326                         return this.resource(endPoint, {}).get();
54327                     };
54328                     APIEndPoint.prototype.getCommands = function () {
54329                         var endPoint = '/api/v1/commandList';
54330                         return this.resource(endPoint, {}).get();
54331                     };
54332                     APIEndPoint.prototype.execute = function (data) {
54333                         var endPoint = '/api/v1/execution';
54334                         var fd = new FormData();
54335                         fd.append('data', data);
54336                         return this.$http.post(endPoint, fd, {
54337                             headers: { 'Content-Type': undefined },
54338                             transformRequest: angular.identity
54339                         });
54340                     };
54341                     APIEndPoint.prototype.debug = function () {
54342                         var endPoint = '/api/v1/debug';
54343                         return this.$http.get(endPoint);
54344                     };
54345 <<<<<<< HEAD
54346                     APIEndPoint.prototype.upload = function () {
54347                         var endPoint = '/api/v1/upload';
54348                         return this.$http.get(endPoint);
54349                     };
54350 =======
54351 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54352                     APIEndPoint.prototype.help = function (command) {
54353                         var endPoint = '/api/v1/help/' + command;
54354                         return this.$http.get(endPoint);
54355                     };
54356                     return APIEndPoint;
54357                 })();
54358                 services.APIEndPoint = APIEndPoint;
54359             })(services = app.services || (app.services = {}));
54360         })(app || (app = {}));
54361         var app;
54362         (function (app) {
54363             var services;
54364             (function (services) {
54365                 var MyModal = (function () {
54366                     function MyModal($uibModal) {
54367                         this.$uibModal = $uibModal;
54368                         this.modalOption = {
54369                             backdrop: true,
54370                             controller: null,
54371                             templateUrl: null,
54372                             size: null
54373                         };
54374                     }
54375                     MyModal.prototype.open = function (modalName) {
54376                         if (modalName === 'SelectCommand') {
54377                             this.modalOption.templateUrl = 'templates/select-command.html';
54378                             this.modalOption.size = 'lg';
54379                         }
54380                         return this.$uibModal.open(this.modalOption);
54381                     };
54382                     MyModal.prototype.selectCommand = function () {
54383                         this.modalOption.templateUrl = 'templates/select-command.html';
54384                         this.modalOption.controller = 'selectCommandController';
54385                         this.modalOption.controllerAs = 'c';
54386                         this.modalOption.size = 'lg';
54387                         return this.$uibModal.open(this.modalOption);
54388                     };
54389                     MyModal.prototype.preview = function () {
54390                         this.modalOption.templateUrl = 'templates/preview.html';
54391                         this.modalOption.controller = 'previewController';
54392                         this.modalOption.controllerAs = 'c';
54393                         this.modalOption.size = 'lg';
54394                         return this.$uibModal.open(this.modalOption);
54395                     };
54396 <<<<<<< HEAD
54397                     MyModal.prototype.upload = function () {
54398                         this.modalOption.templateUrl = 'templates/upload.html';
54399                         this.modalOption.controller = 'uploadController';
54400                         this.modalOption.controllerAs = 'c';
54401                         this.modalOption.size = 'lg';
54402                         return this.$uibModal.open(this.modalOption);
54403                     };
54404 =======
54405 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54406                     MyModal.$inject = ['$uibModal'];
54407                     return MyModal;
54408                 })();
54409                 services.MyModal = MyModal;
54410             })(services = app.services || (app.services = {}));
54411         })(app || (app = {}));
54412         var app;
54413         (function (app) {
54414             var services;
54415             (function (services) {
54416                 var WebSocket = (function () {
54417                     function WebSocket($rootScope) {
54418                         this.$rootScope = $rootScope;
54419                         this.socket = io.connect();
54420                     }
54421                     WebSocket.prototype.on = function (eventName, callback) {
54422                         var socket = this.socket;
54423                         var rootScope = this.$rootScope;
54424                         socket.on(eventName, function () {
54425                             var args = arguments;
54426                             rootScope.$apply(function () {
54427                                 callback.apply(socket, args);
54428                             });
54429                         });
54430                     };
54431                     WebSocket.prototype.emit = function (eventName, data, callback) {
54432                         var socket = this.socket;
54433                         var rootScope = this.$rootScope;
54434                         this.socket.emit(eventName, data, function () {
54435                             var args = arguments;
54436                             rootScope.$apply(function () {
54437                                 if (callback)
54438                                     callback.apply(socket, args);
54439                             });
54440                         });
54441                     };
54442                     return WebSocket;
54443                 })();
54444                 services.WebSocket = WebSocket;
54445             })(services = app.services || (app.services = {}));
54446         })(app || (app = {}));
54447         var app;
54448         (function (app) {
54449             var services;
54450             (function (services) {
54451                 var Console = (function () {
54452                     function Console(WebSocket, $rootScope) {
54453                         this.WebSocket = WebSocket;
54454                         this.$rootScope = $rootScope;
54455                         this.WebSocket = WebSocket;
54456                         this.$rootScope = $rootScope;
54457                         this.directiveIDs = [];
54458                         var directiveIDs = this.directiveIDs;
54459                         this.WebSocket.on('console', function (d) {
54460                             var id = d.id;
54461                             var message = d.message;
54462                             if (directiveIDs.indexOf(id) > -1) {
54463                                 $rootScope.$emit(id, message);
54464                             }
54465                         });
54466                     }
54467                     Console.prototype.addDirective = function (id) {
54468                         if (!(this.directiveIDs.indexOf(id) > -1)) {
54469                             this.directiveIDs.push(id);
54470                         }
54471                     };
54472                     Console.prototype.removeDirective = function (id) {
54473                         var i = this.directiveIDs.indexOf(id);
54474                         if (i > -1) {
54475                             this.directiveIDs.splice(i, 1);
54476                         }
54477                     };
54478                     Console.prototype.showIDs = function () {
54479                         console.log(this.directiveIDs);
54480                     };
54481                     return Console;
54482                 })();
54483                 services.Console = Console;
54484             })(services = app.services || (app.services = {}));
54485         })(app || (app = {}));
54486         var app;
54487         (function (app) {
54488             var directives;
54489             (function (directives) {
54490                 var Command = (function () {
54491                     function Command() {
54492                         this.restrict = 'E';
54493                         this.replace = true;
54494                         this.scope = true;
54495                         this.controller = 'commandController';
54496                         this.controllerAs = 'ctrl';
54497                         this.bindToController = {
54498                             index: '=',
54499                             name: '=',
54500                             remove: '&',
54501                             list: '='
54502                         };
54503                         this.templateUrl = 'templates/command.html';
54504                     }
54505                     Command.Factory = function () {
54506                         var directive = function () {
54507                             return new Command();
54508                         };
54509                         directive.$inject = [];
54510                         return directive;
54511                     };
54512                     return Command;
54513                 })();
54514                 directives.Command = Command;
54515                 var CommandController = (function () {
54516                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
54517                         this.APIEndPoint = APIEndPoint;
54518                         this.$scope = $scope;
54519                         this.MyModal = MyModal;
54520                         this.WebSocket = WebSocket;
54521                         this.$window = $window;
54522                         this.$rootScope = $rootScope;
54523                         this.Console = Console;
54524                         var controller = this;
54525                         this.APIEndPoint
54526                             .getOptionControlFile(this.name)
54527                             .$promise
54528                             .then(function (result) {
54529                             controller.options = result.info;
54530                         });
54531                         this.APIEndPoint
54532                             .getDirectories()
54533                             .$promise
54534                             .then(function (result) {
54535                             controller.dirs = result.info;
54536                         });
54537                         this.heading = "[" + this.index + "]: dcdFilePrint";
54538                         this.isOpen = true;
54539                         this.$scope.$on('close', function () {
54540                             controller.isOpen = false;
54541                         });
54542                         function guid() {
54543                             function s4() {
54544                                 return Math.floor((1 + Math.random()) * 0x10000)
54545                                     .toString(16)
54546                                     .substring(1);
54547                             }
54548                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
54549                                 s4() + '-' + s4() + s4() + s4();
54550                         }
54551                         this.uuid = guid();
54552                         this.Console.addDirective(this.uuid);
54553                         this.Console.showIDs();
54554                     }
54555                     CommandController.prototype.submit = function () {
54556                         var opt = [];
54557                         angular.forEach(this.options, function (option) {
54558                             var obj = {
54559                                 name: option.option,
54560                                 arguments: []
54561                             };
54562                             angular.forEach(option.arg, function (arg) {
54563                                 if (arg.input) {
54564                                     if (typeof arg.input === 'object') {
54565                                         obj.arguments.push(arg.input.name);
54566                                     }
54567                                     else {
54568                                         obj.arguments.push(arg.input);
54569                                     }
54570                                 }
54571                             });
54572                             if (obj.arguments.length > 0) {
54573                                 opt.push(obj);
54574                             }
54575                         });
54576                         var execObj = {
54577                             command: this.name,
54578                             workspace: this.workspace.fileId,
54579                             options: opt
54580                         };
54581                         this.APIEndPoint
54582                             .execute(JSON.stringify(execObj))
54583                             .then(function (result) {
54584                             console.log(result);
54585                         });
54586                     };
54587                     CommandController.prototype.removeMySelf = function (index) {
54588                         this.$scope.$destroy();
54589                         this.Console.removeDirective(this.uuid);
54590                         this.remove()(index, this.list);
54591                         this.Console.showIDs();
54592                     };
54593                     CommandController.prototype.reloadFiles = function () {
54594                         var _this = this;
54595                         var fileId = this.workspace.fileId;
54596                         this.APIEndPoint
54597                             .getFiles(fileId)
54598                             .$promise
54599                             .then(function (result) {
54600                             var status = result.status;
54601                             if (status === 'success') {
54602                                 _this.files = result.info;
54603                             }
54604                             else {
54605                                 console.log(result.message);
54606                             }
54607                         });
54608                     };
54609                     CommandController.prototype.debug = function () {
54610                         var div = angular.element(this.$window.document).find("div");
54611                         var consoleTag;
54612                         var parametersTag;
54613                         angular.forEach(div, function (v) {
54614                             if (v.className === "panel-body console") {
54615                                 consoleTag = v;
54616                             }
54617                             else if (v.className === "row parameters-console") {
54618                                 parametersTag = v;
54619                             }
54620                         });
54621                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
54622                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
54623                         consoleTag.style.height = consoleHeight;
54624                         consoleTag.style.width = consoleWidth;
54625                     };
54626                     CommandController.prototype.help = function () {
54627                         this.APIEndPoint
54628                             .help(this.name)
54629                             .then(function (result) {
54630                             console.log(result);
54631                         });
54632                     };
54633                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
54634                     return CommandController;
54635                 })();
54636                 directives.CommandController = CommandController;
54637             })(directives = app.directives || (app.directives = {}));
54638         })(app || (app = {}));
54639         var app;
54640         (function (app) {
54641             var directives;
54642             (function (directives) {
54643                 var HeaderMenu = (function () {
54644                     function HeaderMenu() {
54645                         this.restrict = 'E';
54646                         this.replace = true;
54647                         this.templateUrl = 'templates/header-menu.html';
54648                         this.controller = 'HeaderMenuController';
54649                         this.controllerAs = 'hmc';
54650                         this.scope = true;
54651                     }
54652                     HeaderMenu.Factory = function () {
54653                         var directive = function () {
54654                             return new HeaderMenu();
54655                         };
54656                         return directive;
54657                     };
54658                     return HeaderMenu;
54659                 })();
54660                 directives.HeaderMenu = HeaderMenu;
54661                 var HeaderMenuController = (function () {
54662                     function HeaderMenuController($state) {
54663                         this.$state = $state;
54664                         this.isExecution = this.$state.current.name === 'execution';
54665                         this.isWorkspace = this.$state.current.name === 'workspace';
54666                         this.isHistory = this.$state.current.name === 'history';
54667                     }
54668                     HeaderMenuController.prototype.transit = function (state) {
54669                         this.$state.go(state);
54670                     };
54671                     HeaderMenuController.$inject = ['$state'];
54672                     return HeaderMenuController;
54673                 })();
54674                 directives.HeaderMenuController = HeaderMenuController;
54675             })(directives = app.directives || (app.directives = {}));
54676         })(app || (app = {}));
54677         var app;
54678         (function (app) {
54679             var directives;
54680             (function (directives) {
54681                 var Option = (function () {
54682                     function Option() {
54683                         this.restrict = 'E';
54684                         this.replace = true;
54685                         this.controller = 'optionController';
54686                         this.bindToController = {
54687                             info: '=',
54688                             files: '='
54689                         };
54690                         this.scope = true;
54691                         this.templateUrl = 'templates/option.html';
54692                         this.controllerAs = 'ctrl';
54693                     }
54694                     Option.Factory = function () {
54695                         var directive = function () {
54696                             return new Option();
54697                         };
54698                         directive.$inject = [];
54699                         return directive;
54700                     };
54701                     return Option;
54702                 })();
54703                 directives.Option = Option;
54704                 var OptionController = (function () {
54705                     function OptionController() {
54706                         var controller = this;
54707                         angular.forEach(controller.info.arg, function (arg) {
54708                             if (arg.initialValue) {
54709                                 if (arg.formType === 'number') {
54710                                     arg.input = parseInt(arg.initialValue);
54711                                 }
54712                                 else {
54713                                     arg.input = arg.initialValue;
54714                                 }
54715                             }
54716                         });
54717                     }
54718                     OptionController.$inject = [];
54719                     return OptionController;
54720                 })();
54721                 directives.OptionController = OptionController;
54722             })(directives = app.directives || (app.directives = {}));
54723         })(app || (app = {}));
54724         var app;
54725         (function (app) {
54726             var directives;
54727             (function (directives) {
54728                 var Directory = (function () {
54729                     function Directory() {
54730                         this.restrict = 'E';
54731                         this.replace = true;
54732                         this.controller = 'directoryController';
54733                         this.controllerAs = 'ctrl';
54734                         this.bindToController = {
54735                             info: '=',
54736                             add: '&',
54737                             list: '=',
54738                             files: '='
54739                         };
54740                         this.templateUrl = 'templates/directory.html';
54741                     }
54742                     Directory.Factory = function () {
54743                         var directive = function () {
54744                             return new Directory();
54745                         };
54746                         return directive;
54747                     };
54748                     return Directory;
54749                 })();
54750                 directives.Directory = Directory;
54751                 var DirectoryController = (function () {
54752                     function DirectoryController(APIEndPoint, $scope) {
54753                         this.APIEndPoint = APIEndPoint;
54754                         this.$scope = $scope;
54755                         var controller = this;
54756                         this.APIEndPoint
54757                             .getFiles(this.info.fileId)
54758                             .$promise
54759                             .then(function (result) {
54760                             if (result.status === 'success') {
54761                                 controller.files = result.info;
54762                                 angular.forEach(result.info, function (file) {
54763                                     if (file.fileType === '0') {
54764                                         var o = file;
54765                                         if (controller.info.path === '/') {
54766                                             o.path = '/' + file.name;
54767                                         }
54768                                         else {
54769                                             o.path = controller.info.path + '/' + file.name;
54770                                         }
54771                                         controller.add()(o, controller.list);
54772                                     }
54773                                 });
54774                             }
54775                             ;
54776                         });
54777                     }
54778                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
54779                     return DirectoryController;
54780                 })();
54781                 directives.DirectoryController = DirectoryController;
54782             })(directives = app.directives || (app.directives = {}));
54783         })(app || (app = {}));
54784         var app;
54785         (function (app) {
54786 <<<<<<< HEAD
54787             var directives;
54788             (function (directives) {
54789                 var Upload = (function () {
54790                     function Upload() {
54791                         this.restrict = 'E';
54792                         this.replace = true;
54793                         this.scope = true;
54794                         this.controller = 'UploadController';
54795                         this.controllerAs = 'ctrl';
54796                         this.bindToController = {
54797                             index: '=',
54798                             name: '=',
54799                             remove: '&',
54800                             list: '='
54801                         };
54802                         this.templateUrl = 'templates/upload.html';
54803                         console.log("templates/upload.html-constructor");
54804                     }
54805                     Upload.Factory = function () {
54806                         var directive = function () {
54807                             return new Upload();
54808                         };
54809                         directive.$inject = [];
54810                         return directive;
54811                     };
54812                     return Upload;
54813                 })();
54814                 directives.Upload = Upload;
54815                 var UploadController = (function () {
54816                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
54817                         this.APIEndPoint = APIEndPoint;
54818                         this.$scope = $scope;
54819                         this.MyModal = MyModal;
54820                         this.WebSocket = WebSocket;
54821                         this.$window = $window;
54822                         this.$rootScope = $rootScope;
54823                         this.Console = Console;
54824                         var controller = this;
54825                         console.log("directive.upload-constructor");
54826                     }
54827                     UploadController.prototype.submit = function () {
54828                         console.log("submit: function not supported¥n");
54829                     };
54830                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
54831                     return UploadController;
54832                 })();
54833                 directives.UploadController = UploadController;
54834             })(directives = app.directives || (app.directives = {}));
54835         })(app || (app = {}));
54836         var app;
54837         (function (app) {
54838 =======
54839 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54840             var controllers;
54841             (function (controllers) {
54842                 var Execution = (function () {
54843                     function Execution(MyModal, $scope) {
54844                         this.MyModal = MyModal;
54845                         this.$scope = $scope;
54846                         this.commandInfoList = [];
54847                     }
54848                     ;
54849                     Execution.prototype.add = function () {
54850                         this.$scope.$broadcast('close');
54851                         var commandInfoList = this.commandInfoList;
54852                         var commandInstance = this.MyModal.selectCommand();
54853                         commandInstance
54854                             .result
54855                             .then(function (command) {
54856                             commandInfoList.push(new app.declares.CommandInfo(command));
54857                         });
54858                     };
54859                     Execution.prototype.open = function () {
54860                         var result = this.MyModal.open('SelectCommand');
54861                         console.log(result);
54862                     };
54863                     Execution.prototype.remove = function (index, list) {
54864                         list.splice(index, 1);
54865                     };
54866                     Execution.prototype.close = function () {
54867                         console.log("close");
54868                     };
54869                     Execution.$inject = ['MyModal', '$scope'];
54870                     return Execution;
54871                 })();
54872                 controllers.Execution = Execution;
54873             })(controllers = app.controllers || (app.controllers = {}));
54874         })(app || (app = {}));
54875         var app;
54876         (function (app) {
54877             var controllers;
54878             (function (controllers) {
54879                 var Workspace = (function () {
54880                     function Workspace($scope, APIEndPoint, MyModal) {
54881                         this.$scope = $scope;
54882                         this.APIEndPoint = APIEndPoint;
54883                         this.MyModal = MyModal;
54884                         this.directoryList = [];
54885                         var controller = this;
54886                         var directoryList = this.directoryList;
54887                         var o = {
54888                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
54889                             name: '',
54890                             parentId: '',
54891                             fileType: '',
54892                             createdAt: '',
54893                             updatedAt: '',
54894                             path: '/'
54895                         };
54896                         directoryList.push(o);
54897                     }
54898                     Workspace.prototype.addDirectory = function (info, directoryList) {
54899                         directoryList.push(info);
54900                     };
54901 <<<<<<< HEAD
54902                     Workspace.prototype.upload = function () {
54903                         this.MyModal.upload();
54904                     };
54905 =======
54906 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54907                     Workspace.prototype.debug = function () {
54908                         this.MyModal.preview();
54909                     };
54910                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
54911                     return Workspace;
54912                 })();
54913                 controllers.Workspace = Workspace;
54914             })(controllers = app.controllers || (app.controllers = {}));
54915         })(app || (app = {}));
54916         var app;
54917         (function (app) {
54918             var controllers;
54919             (function (controllers) {
54920                 var History = (function () {
54921                     function History($scope) {
54922                         this.page = "History";
54923                     }
54924                     History.$inject = ['$scope'];
54925                     return History;
54926                 })();
54927                 controllers.History = History;
54928             })(controllers = app.controllers || (app.controllers = {}));
54929         })(app || (app = {}));
54930         var app;
54931         (function (app) {
54932             var controllers;
54933             (function (controllers) {
54934                 var SelectCommand = (function () {
54935                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
54936                         this.APIEndPoint = APIEndPoint;
54937                         this.$modalInstance = $modalInstance;
54938                         var controller = this;
54939                         this.APIEndPoint
54940                             .getTags()
54941                             .$promise.then(function (result) {
54942                             controller.tags = result.info;
54943                         });
54944                         this.APIEndPoint
54945                             .getCommands()
54946                             .$promise.then(function (result) {
54947                             controller.commands = result.info;
54948                         });
54949                         this.currentTag = 'all';
54950                     }
54951                     SelectCommand.prototype.changeTag = function (tag) {
54952                         this.currentTag = tag;
54953                     };
54954                     SelectCommand.prototype.selectCommand = function (command) {
54955                         this.$modalInstance.close(command);
54956                     };
54957                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
54958                     return SelectCommand;
54959                 })();
54960                 controllers.SelectCommand = SelectCommand;
54961             })(controllers = app.controllers || (app.controllers = {}));
54962         })(app || (app = {}));
54963         var app;
54964         (function (app) {
54965             var controllers;
54966             (function (controllers) {
54967 <<<<<<< HEAD
54968                 var Upload = (function () {
54969                     function Upload($scope, APIEndPoint, $modalInstance) {
54970                         this.APIEndPoint = APIEndPoint;
54971                         this.$modalInstance = $modalInstance;
54972                         var controller = this;
54973                         console.log('controller.upload-controllers');
54974                     }
54975                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
54976                     return Upload;
54977                 })();
54978                 controllers.Upload = Upload;
54979             })(controllers = app.controllers || (app.controllers = {}));
54980         })(app || (app = {}));
54981         var app;
54982         (function (app) {
54983             var controllers;
54984             (function (controllers) {
54985 =======
54986 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
54987                 var Preview = (function () {
54988                     function Preview($scope, APIEndPoint, $modalInstance) {
54989                         this.APIEndPoint = APIEndPoint;
54990                         this.$modalInstance = $modalInstance;
54991                         var controller = this;
54992                         console.log('preview');
54993                     }
54994                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
54995                     return Preview;
54996                 })();
54997                 controllers.Preview = Preview;
54998             })(controllers = app.controllers || (app.controllers = {}));
54999         })(app || (app = {}));
55000         var filters;
55001         (function (filters) {
55002             function Tag() {
55003                 return function (commands, tag) {
55004                     var result = [];
55005                     angular.forEach(commands, function (command) {
55006                         var flag = false;
55007                         angular.forEach(command.tags, function (value) {
55008                             if (tag === value)
55009                                 flag = true;
55010                         });
55011                         if (flag)
55012                             result.push(command);
55013                     });
55014                     return result;
55015                 };
55016             }
55017             filters.Tag = Tag;
55018         })(filters || (filters = {}));
55019         var app;
55020         (function (app) {
55021             'use strict';
55022             var appName = 'zephyr';
55023             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
55024             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
55025                 $urlRouterProvider.otherwise('/execution');
55026                 $locationProvider.html5Mode({
55027                     enabled: true,
55028                     requireBase: false
55029                 });
55030                 $stateProvider
55031                     .state('execution', {
55032                     url: '/execution',
55033                     templateUrl: 'templates/execution.html',
55034                     controller: 'executionController',
55035                     controllerAs: 'c'
55036                 })
55037                     .state('workspace', {
55038                     url: '/workspace',
55039                     templateUrl: 'templates/workspace.html',
55040                     controller: 'workspaceController',
55041                     controllerAs: 'c'
55042                 })
55043                     .state('history', {
55044                     url: '/history',
55045                     templateUrl: 'templates/history.html',
55046                     controller: 'historyController',
55047                     controllerAs: 'c'
55048                 });
55049             });
55050             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
55051             app.zephyr.service('MyModal', app.services.MyModal);
55052             app.zephyr.service('WebSocket', app.services.WebSocket);
55053             app.zephyr.service('Console', app.services.Console);
55054             app.zephyr.filter('Tag', filters.Tag);
55055             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
55056             app.zephyr.controller('previewController', app.controllers.Preview);
55057 <<<<<<< HEAD
55058             app.zephyr.controller('uploadController', app.controllers.Upload);
55059 =======
55060 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55061             app.zephyr.controller('executionController', app.controllers.Execution);
55062             app.zephyr.controller('workspaceController', app.controllers.Workspace);
55063             app.zephyr.controller('historyController', app.controllers.History);
55064             app.zephyr.controller('commandController', app.directives.CommandController);
55065             app.zephyr.controller('optionController', app.directives.OptionController);
55066             app.zephyr.controller('directoryController', app.directives.DirectoryController);
55067             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
55068 <<<<<<< HEAD
55069             app.zephyr.controller('uploadController', app.directives.UploadController);
55070 =======
55071 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55072             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
55073             app.zephyr.directive('command', app.directives.Command.Factory());
55074             app.zephyr.directive('option', app.directives.Option.Factory());
55075             app.zephyr.directive('directory', app.directives.Directory.Factory());
55076         })(app || (app = {}));
55077
55078
55079 /***/ },
55080 <<<<<<< HEAD
55081 /* 20 */
55082 =======
55083 /* 18 */
55084 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55085 /***/ function(module, exports) {
55086
55087         var app;
55088         (function (app) {
55089             var declares;
55090             (function (declares) {
55091                 var CommandInfo = (function () {
55092                     function CommandInfo(name) {
55093                         this.name = name;
55094                     }
55095                     return CommandInfo;
55096                 })();
55097                 declares.CommandInfo = CommandInfo;
55098             })(declares = app.declares || (app.declares = {}));
55099         })(app || (app = {}));
55100         var app;
55101         (function (app) {
55102             var services;
55103             (function (services) {
55104                 var APIEndPoint = (function () {
55105                     function APIEndPoint($resource, $http) {
55106                         this.$resource = $resource;
55107                         this.$http = $http;
55108                     }
55109                     APIEndPoint.prototype.resource = function (endPoint, data) {
55110                         var customAction = {
55111                             method: 'GET',
55112                             isArray: false
55113                         };
55114                         var execute = {
55115                             method: 'POST',
55116                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
55117                         };
55118                         return this.$resource(endPoint, {}, { execute: execute });
55119                     };
55120                     APIEndPoint.prototype.getOptionControlFile = function (command) {
55121                         var endPoint = '/api/v1/optionControlFile/' + command;
55122                         return this.resource(endPoint, {}).get();
55123                     };
55124                     APIEndPoint.prototype.getFiles = function (fileId) {
55125                         var endPoint = '/api/v1/workspace';
55126                         if (fileId) {
55127                             endPoint += '/' + fileId;
55128                         }
55129                         return this.resource(endPoint, {}).get();
55130                     };
55131                     APIEndPoint.prototype.getDirectories = function () {
55132                         var endPoint = '/api/v1/all/workspace/directory';
55133                         return this.resource(endPoint, {}).get();
55134                     };
55135                     APIEndPoint.prototype.getTags = function () {
55136                         var endPoint = '/api/v1/tagList';
55137                         return this.resource(endPoint, {}).get();
55138                     };
55139                     APIEndPoint.prototype.getCommands = function () {
55140                         var endPoint = '/api/v1/commandList';
55141                         return this.resource(endPoint, {}).get();
55142                     };
55143                     APIEndPoint.prototype.execute = function (data) {
55144                         var endPoint = '/api/v1/execution';
55145                         var fd = new FormData();
55146                         fd.append('data', data);
55147                         return this.$http.post(endPoint, fd, {
55148                             headers: { 'Content-Type': undefined },
55149                             transformRequest: angular.identity
55150                         });
55151                     };
55152                     APIEndPoint.prototype.debug = function () {
55153                         var endPoint = '/api/v1/debug';
55154                         return this.$http.get(endPoint);
55155                     };
55156 <<<<<<< HEAD
55157                     APIEndPoint.prototype.upload = function () {
55158                         var endPoint = '/api/v1/upload';
55159                         return this.$http.get(endPoint);
55160                     };
55161 =======
55162 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55163                     APIEndPoint.prototype.help = function (command) {
55164                         var endPoint = '/api/v1/help/' + command;
55165                         return this.$http.get(endPoint);
55166                     };
55167                     return APIEndPoint;
55168                 })();
55169                 services.APIEndPoint = APIEndPoint;
55170             })(services = app.services || (app.services = {}));
55171         })(app || (app = {}));
55172         var app;
55173         (function (app) {
55174             var services;
55175             (function (services) {
55176                 var MyModal = (function () {
55177                     function MyModal($uibModal) {
55178                         this.$uibModal = $uibModal;
55179                         this.modalOption = {
55180                             backdrop: true,
55181                             controller: null,
55182                             templateUrl: null,
55183                             size: null
55184                         };
55185                     }
55186                     MyModal.prototype.open = function (modalName) {
55187                         if (modalName === 'SelectCommand') {
55188                             this.modalOption.templateUrl = 'templates/select-command.html';
55189                             this.modalOption.size = 'lg';
55190                         }
55191                         return this.$uibModal.open(this.modalOption);
55192                     };
55193                     MyModal.prototype.selectCommand = function () {
55194                         this.modalOption.templateUrl = 'templates/select-command.html';
55195                         this.modalOption.controller = 'selectCommandController';
55196                         this.modalOption.controllerAs = 'c';
55197                         this.modalOption.size = 'lg';
55198                         return this.$uibModal.open(this.modalOption);
55199                     };
55200                     MyModal.prototype.preview = function () {
55201                         this.modalOption.templateUrl = 'templates/preview.html';
55202                         this.modalOption.controller = 'previewController';
55203                         this.modalOption.controllerAs = 'c';
55204                         this.modalOption.size = 'lg';
55205                         return this.$uibModal.open(this.modalOption);
55206                     };
55207 <<<<<<< HEAD
55208                     MyModal.prototype.upload = function () {
55209                         this.modalOption.templateUrl = 'templates/upload.html';
55210                         this.modalOption.controller = 'uploadController';
55211                         this.modalOption.controllerAs = 'c';
55212                         this.modalOption.size = 'lg';
55213                         return this.$uibModal.open(this.modalOption);
55214                     };
55215 =======
55216 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55217                     MyModal.$inject = ['$uibModal'];
55218                     return MyModal;
55219                 })();
55220                 services.MyModal = MyModal;
55221             })(services = app.services || (app.services = {}));
55222         })(app || (app = {}));
55223         var app;
55224         (function (app) {
55225             var services;
55226             (function (services) {
55227                 var WebSocket = (function () {
55228                     function WebSocket($rootScope) {
55229                         this.$rootScope = $rootScope;
55230                         this.socket = io.connect();
55231                     }
55232                     WebSocket.prototype.on = function (eventName, callback) {
55233                         var socket = this.socket;
55234                         var rootScope = this.$rootScope;
55235                         socket.on(eventName, function () {
55236                             var args = arguments;
55237                             rootScope.$apply(function () {
55238                                 callback.apply(socket, args);
55239                             });
55240                         });
55241                     };
55242                     WebSocket.prototype.emit = function (eventName, data, callback) {
55243                         var socket = this.socket;
55244                         var rootScope = this.$rootScope;
55245                         this.socket.emit(eventName, data, function () {
55246                             var args = arguments;
55247                             rootScope.$apply(function () {
55248                                 if (callback)
55249                                     callback.apply(socket, args);
55250                             });
55251                         });
55252                     };
55253                     return WebSocket;
55254                 })();
55255                 services.WebSocket = WebSocket;
55256             })(services = app.services || (app.services = {}));
55257         })(app || (app = {}));
55258         var app;
55259         (function (app) {
55260             var services;
55261             (function (services) {
55262                 var Console = (function () {
55263                     function Console(WebSocket, $rootScope) {
55264                         this.WebSocket = WebSocket;
55265                         this.$rootScope = $rootScope;
55266                         this.WebSocket = WebSocket;
55267                         this.$rootScope = $rootScope;
55268                         this.directiveIDs = [];
55269                         var directiveIDs = this.directiveIDs;
55270                         this.WebSocket.on('console', function (d) {
55271                             var id = d.id;
55272                             var message = d.message;
55273                             if (directiveIDs.indexOf(id) > -1) {
55274                                 $rootScope.$emit(id, message);
55275                             }
55276                         });
55277                     }
55278                     Console.prototype.addDirective = function (id) {
55279                         if (!(this.directiveIDs.indexOf(id) > -1)) {
55280                             this.directiveIDs.push(id);
55281                         }
55282                     };
55283                     Console.prototype.removeDirective = function (id) {
55284                         var i = this.directiveIDs.indexOf(id);
55285                         if (i > -1) {
55286                             this.directiveIDs.splice(i, 1);
55287                         }
55288                     };
55289                     Console.prototype.showIDs = function () {
55290                         console.log(this.directiveIDs);
55291                     };
55292                     return Console;
55293                 })();
55294                 services.Console = Console;
55295             })(services = app.services || (app.services = {}));
55296         })(app || (app = {}));
55297         var app;
55298         (function (app) {
55299             var directives;
55300             (function (directives) {
55301                 var Command = (function () {
55302                     function Command() {
55303                         this.restrict = 'E';
55304                         this.replace = true;
55305                         this.scope = true;
55306                         this.controller = 'commandController';
55307                         this.controllerAs = 'ctrl';
55308                         this.bindToController = {
55309                             index: '=',
55310                             name: '=',
55311                             remove: '&',
55312                             list: '='
55313                         };
55314                         this.templateUrl = 'templates/command.html';
55315                     }
55316                     Command.Factory = function () {
55317                         var directive = function () {
55318                             return new Command();
55319                         };
55320                         directive.$inject = [];
55321                         return directive;
55322                     };
55323                     return Command;
55324                 })();
55325                 directives.Command = Command;
55326                 var CommandController = (function () {
55327                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
55328                         this.APIEndPoint = APIEndPoint;
55329                         this.$scope = $scope;
55330                         this.MyModal = MyModal;
55331                         this.WebSocket = WebSocket;
55332                         this.$window = $window;
55333                         this.$rootScope = $rootScope;
55334                         this.Console = Console;
55335                         var controller = this;
55336                         this.APIEndPoint
55337                             .getOptionControlFile(this.name)
55338                             .$promise
55339                             .then(function (result) {
55340                             controller.options = result.info;
55341                         });
55342                         this.APIEndPoint
55343                             .getDirectories()
55344                             .$promise
55345                             .then(function (result) {
55346                             controller.dirs = result.info;
55347                         });
55348                         this.heading = "[" + this.index + "]: dcdFilePrint";
55349                         this.isOpen = true;
55350                         this.$scope.$on('close', function () {
55351                             controller.isOpen = false;
55352                         });
55353                         function guid() {
55354                             function s4() {
55355                                 return Math.floor((1 + Math.random()) * 0x10000)
55356                                     .toString(16)
55357                                     .substring(1);
55358                             }
55359                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
55360                                 s4() + '-' + s4() + s4() + s4();
55361                         }
55362                         this.uuid = guid();
55363                         this.Console.addDirective(this.uuid);
55364                         this.Console.showIDs();
55365                     }
55366                     CommandController.prototype.submit = function () {
55367                         var opt = [];
55368                         angular.forEach(this.options, function (option) {
55369                             var obj = {
55370                                 name: option.option,
55371                                 arguments: []
55372                             };
55373                             angular.forEach(option.arg, function (arg) {
55374                                 if (arg.input) {
55375                                     if (typeof arg.input === 'object') {
55376                                         obj.arguments.push(arg.input.name);
55377                                     }
55378                                     else {
55379                                         obj.arguments.push(arg.input);
55380                                     }
55381                                 }
55382                             });
55383                             if (obj.arguments.length > 0) {
55384                                 opt.push(obj);
55385                             }
55386                         });
55387                         var execObj = {
55388                             command: this.name,
55389                             workspace: this.workspace.fileId,
55390                             options: opt
55391                         };
55392                         this.APIEndPoint
55393                             .execute(JSON.stringify(execObj))
55394                             .then(function (result) {
55395                             console.log(result);
55396                         });
55397                     };
55398                     CommandController.prototype.removeMySelf = function (index) {
55399                         this.$scope.$destroy();
55400                         this.Console.removeDirective(this.uuid);
55401                         this.remove()(index, this.list);
55402                         this.Console.showIDs();
55403                     };
55404                     CommandController.prototype.reloadFiles = function () {
55405                         var _this = this;
55406                         var fileId = this.workspace.fileId;
55407                         this.APIEndPoint
55408                             .getFiles(fileId)
55409                             .$promise
55410                             .then(function (result) {
55411                             var status = result.status;
55412                             if (status === 'success') {
55413                                 _this.files = result.info;
55414                             }
55415                             else {
55416                                 console.log(result.message);
55417                             }
55418                         });
55419                     };
55420                     CommandController.prototype.debug = function () {
55421                         var div = angular.element(this.$window.document).find("div");
55422                         var consoleTag;
55423                         var parametersTag;
55424                         angular.forEach(div, function (v) {
55425                             if (v.className === "panel-body console") {
55426                                 consoleTag = v;
55427                             }
55428                             else if (v.className === "row parameters-console") {
55429                                 parametersTag = v;
55430                             }
55431                         });
55432                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
55433                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
55434                         consoleTag.style.height = consoleHeight;
55435                         consoleTag.style.width = consoleWidth;
55436                     };
55437                     CommandController.prototype.help = function () {
55438                         this.APIEndPoint
55439                             .help(this.name)
55440                             .then(function (result) {
55441                             console.log(result);
55442                         });
55443                     };
55444                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
55445                     return CommandController;
55446                 })();
55447                 directives.CommandController = CommandController;
55448             })(directives = app.directives || (app.directives = {}));
55449         })(app || (app = {}));
55450         var app;
55451         (function (app) {
55452             var directives;
55453             (function (directives) {
55454                 var HeaderMenu = (function () {
55455                     function HeaderMenu() {
55456                         this.restrict = 'E';
55457                         this.replace = true;
55458                         this.templateUrl = 'templates/header-menu.html';
55459                         this.controller = 'HeaderMenuController';
55460                         this.controllerAs = 'hmc';
55461                         this.scope = true;
55462                     }
55463                     HeaderMenu.Factory = function () {
55464                         var directive = function () {
55465                             return new HeaderMenu();
55466                         };
55467                         return directive;
55468                     };
55469                     return HeaderMenu;
55470                 })();
55471                 directives.HeaderMenu = HeaderMenu;
55472                 var HeaderMenuController = (function () {
55473                     function HeaderMenuController($state) {
55474                         this.$state = $state;
55475                         this.isExecution = this.$state.current.name === 'execution';
55476                         this.isWorkspace = this.$state.current.name === 'workspace';
55477                         this.isHistory = this.$state.current.name === 'history';
55478                     }
55479                     HeaderMenuController.prototype.transit = function (state) {
55480                         this.$state.go(state);
55481                     };
55482                     HeaderMenuController.$inject = ['$state'];
55483                     return HeaderMenuController;
55484                 })();
55485                 directives.HeaderMenuController = HeaderMenuController;
55486             })(directives = app.directives || (app.directives = {}));
55487         })(app || (app = {}));
55488         var app;
55489         (function (app) {
55490             var directives;
55491             (function (directives) {
55492                 var Option = (function () {
55493                     function Option() {
55494                         this.restrict = 'E';
55495                         this.replace = true;
55496                         this.controller = 'optionController';
55497                         this.bindToController = {
55498                             info: '=',
55499                             files: '='
55500                         };
55501                         this.scope = true;
55502                         this.templateUrl = 'templates/option.html';
55503                         this.controllerAs = 'ctrl';
55504                     }
55505                     Option.Factory = function () {
55506                         var directive = function () {
55507                             return new Option();
55508                         };
55509                         directive.$inject = [];
55510                         return directive;
55511                     };
55512                     return Option;
55513                 })();
55514                 directives.Option = Option;
55515                 var OptionController = (function () {
55516                     function OptionController() {
55517                         var controller = this;
55518                         angular.forEach(controller.info.arg, function (arg) {
55519                             if (arg.initialValue) {
55520                                 if (arg.formType === 'number') {
55521                                     arg.input = parseInt(arg.initialValue);
55522                                 }
55523                                 else {
55524                                     arg.input = arg.initialValue;
55525                                 }
55526                             }
55527                         });
55528                     }
55529                     OptionController.$inject = [];
55530                     return OptionController;
55531                 })();
55532                 directives.OptionController = OptionController;
55533             })(directives = app.directives || (app.directives = {}));
55534         })(app || (app = {}));
55535         var app;
55536         (function (app) {
55537             var directives;
55538             (function (directives) {
55539                 var Directory = (function () {
55540                     function Directory() {
55541                         this.restrict = 'E';
55542                         this.replace = true;
55543                         this.controller = 'directoryController';
55544                         this.controllerAs = 'ctrl';
55545                         this.bindToController = {
55546                             info: '=',
55547                             add: '&',
55548                             list: '=',
55549                             files: '='
55550                         };
55551                         this.templateUrl = 'templates/directory.html';
55552                     }
55553                     Directory.Factory = function () {
55554                         var directive = function () {
55555                             return new Directory();
55556                         };
55557                         return directive;
55558                     };
55559                     return Directory;
55560                 })();
55561                 directives.Directory = Directory;
55562                 var DirectoryController = (function () {
55563                     function DirectoryController(APIEndPoint, $scope) {
55564                         this.APIEndPoint = APIEndPoint;
55565                         this.$scope = $scope;
55566                         var controller = this;
55567                         this.APIEndPoint
55568                             .getFiles(this.info.fileId)
55569                             .$promise
55570                             .then(function (result) {
55571                             if (result.status === 'success') {
55572                                 controller.files = result.info;
55573                                 angular.forEach(result.info, function (file) {
55574                                     if (file.fileType === '0') {
55575                                         var o = file;
55576                                         if (controller.info.path === '/') {
55577                                             o.path = '/' + file.name;
55578                                         }
55579                                         else {
55580                                             o.path = controller.info.path + '/' + file.name;
55581                                         }
55582                                         controller.add()(o, controller.list);
55583                                     }
55584                                 });
55585                             }
55586                             ;
55587                         });
55588                     }
55589                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
55590                     return DirectoryController;
55591                 })();
55592                 directives.DirectoryController = DirectoryController;
55593             })(directives = app.directives || (app.directives = {}));
55594         })(app || (app = {}));
55595         var app;
55596         (function (app) {
55597 <<<<<<< HEAD
55598             var directives;
55599             (function (directives) {
55600                 var Upload = (function () {
55601                     function Upload() {
55602                         this.restrict = 'E';
55603                         this.replace = true;
55604                         this.scope = true;
55605                         this.controller = 'UploadController';
55606                         this.controllerAs = 'ctrl';
55607                         this.bindToController = {
55608                             index: '=',
55609                             name: '=',
55610                             remove: '&',
55611                             list: '='
55612                         };
55613                         this.templateUrl = 'templates/upload.html';
55614                         console.log("templates/upload.html-constructor");
55615                     }
55616                     Upload.Factory = function () {
55617                         var directive = function () {
55618                             return new Upload();
55619                         };
55620                         directive.$inject = [];
55621                         return directive;
55622                     };
55623                     return Upload;
55624                 })();
55625                 directives.Upload = Upload;
55626                 var UploadController = (function () {
55627                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
55628                         this.APIEndPoint = APIEndPoint;
55629                         this.$scope = $scope;
55630                         this.MyModal = MyModal;
55631                         this.WebSocket = WebSocket;
55632                         this.$window = $window;
55633                         this.$rootScope = $rootScope;
55634                         this.Console = Console;
55635                         var controller = this;
55636                         console.log("directive.upload-constructor");
55637                     }
55638                     UploadController.prototype.submit = function () {
55639                         console.log("submit: function not supported¥n");
55640                     };
55641                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
55642                     return UploadController;
55643                 })();
55644                 directives.UploadController = UploadController;
55645             })(directives = app.directives || (app.directives = {}));
55646         })(app || (app = {}));
55647         var app;
55648         (function (app) {
55649 =======
55650 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55651             var controllers;
55652             (function (controllers) {
55653                 var Execution = (function () {
55654                     function Execution(MyModal, $scope) {
55655                         this.MyModal = MyModal;
55656                         this.$scope = $scope;
55657                         this.commandInfoList = [];
55658                     }
55659                     ;
55660                     Execution.prototype.add = function () {
55661                         this.$scope.$broadcast('close');
55662                         var commandInfoList = this.commandInfoList;
55663                         var commandInstance = this.MyModal.selectCommand();
55664                         commandInstance
55665                             .result
55666                             .then(function (command) {
55667                             commandInfoList.push(new app.declares.CommandInfo(command));
55668                         });
55669                     };
55670                     Execution.prototype.open = function () {
55671                         var result = this.MyModal.open('SelectCommand');
55672                         console.log(result);
55673                     };
55674                     Execution.prototype.remove = function (index, list) {
55675                         list.splice(index, 1);
55676                     };
55677                     Execution.prototype.close = function () {
55678                         console.log("close");
55679                     };
55680                     Execution.$inject = ['MyModal', '$scope'];
55681                     return Execution;
55682                 })();
55683                 controllers.Execution = Execution;
55684             })(controllers = app.controllers || (app.controllers = {}));
55685         })(app || (app = {}));
55686         var app;
55687         (function (app) {
55688             var controllers;
55689             (function (controllers) {
55690                 var Workspace = (function () {
55691                     function Workspace($scope, APIEndPoint, MyModal) {
55692                         this.$scope = $scope;
55693                         this.APIEndPoint = APIEndPoint;
55694                         this.MyModal = MyModal;
55695                         this.directoryList = [];
55696                         var controller = this;
55697                         var directoryList = this.directoryList;
55698                         var o = {
55699                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
55700                             name: '',
55701                             parentId: '',
55702                             fileType: '',
55703                             createdAt: '',
55704                             updatedAt: '',
55705                             path: '/'
55706                         };
55707                         directoryList.push(o);
55708                     }
55709                     Workspace.prototype.addDirectory = function (info, directoryList) {
55710                         directoryList.push(info);
55711                     };
55712 <<<<<<< HEAD
55713                     Workspace.prototype.upload = function () {
55714                         this.MyModal.upload();
55715                     };
55716 =======
55717 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55718                     Workspace.prototype.debug = function () {
55719                         this.MyModal.preview();
55720                     };
55721                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
55722                     return Workspace;
55723                 })();
55724                 controllers.Workspace = Workspace;
55725             })(controllers = app.controllers || (app.controllers = {}));
55726         })(app || (app = {}));
55727         var app;
55728         (function (app) {
55729             var controllers;
55730             (function (controllers) {
55731                 var History = (function () {
55732                     function History($scope) {
55733                         this.page = "History";
55734                     }
55735                     History.$inject = ['$scope'];
55736                     return History;
55737                 })();
55738                 controllers.History = History;
55739             })(controllers = app.controllers || (app.controllers = {}));
55740         })(app || (app = {}));
55741         var app;
55742         (function (app) {
55743             var controllers;
55744             (function (controllers) {
55745                 var SelectCommand = (function () {
55746                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
55747                         this.APIEndPoint = APIEndPoint;
55748                         this.$modalInstance = $modalInstance;
55749                         var controller = this;
55750                         this.APIEndPoint
55751                             .getTags()
55752                             .$promise.then(function (result) {
55753                             controller.tags = result.info;
55754                         });
55755                         this.APIEndPoint
55756                             .getCommands()
55757                             .$promise.then(function (result) {
55758                             controller.commands = result.info;
55759                         });
55760                         this.currentTag = 'all';
55761                     }
55762                     SelectCommand.prototype.changeTag = function (tag) {
55763                         this.currentTag = tag;
55764                     };
55765                     SelectCommand.prototype.selectCommand = function (command) {
55766                         this.$modalInstance.close(command);
55767                     };
55768                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
55769                     return SelectCommand;
55770                 })();
55771                 controllers.SelectCommand = SelectCommand;
55772             })(controllers = app.controllers || (app.controllers = {}));
55773         })(app || (app = {}));
55774         var app;
55775         (function (app) {
55776             var controllers;
55777             (function (controllers) {
55778 <<<<<<< HEAD
55779                 var Upload = (function () {
55780                     function Upload($scope, APIEndPoint, $modalInstance) {
55781                         this.APIEndPoint = APIEndPoint;
55782                         this.$modalInstance = $modalInstance;
55783                         var controller = this;
55784                         console.log('controller.upload-controllers');
55785                     }
55786                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
55787                     return Upload;
55788                 })();
55789                 controllers.Upload = Upload;
55790             })(controllers = app.controllers || (app.controllers = {}));
55791         })(app || (app = {}));
55792         var app;
55793         (function (app) {
55794             var controllers;
55795             (function (controllers) {
55796 =======
55797 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55798                 var Preview = (function () {
55799                     function Preview($scope, APIEndPoint, $modalInstance) {
55800                         this.APIEndPoint = APIEndPoint;
55801                         this.$modalInstance = $modalInstance;
55802                         var controller = this;
55803                         console.log('preview');
55804                     }
55805                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
55806                     return Preview;
55807                 })();
55808                 controllers.Preview = Preview;
55809             })(controllers = app.controllers || (app.controllers = {}));
55810         })(app || (app = {}));
55811         var filters;
55812         (function (filters) {
55813             function Tag() {
55814                 return function (commands, tag) {
55815                     var result = [];
55816                     angular.forEach(commands, function (command) {
55817                         var flag = false;
55818                         angular.forEach(command.tags, function (value) {
55819                             if (tag === value)
55820                                 flag = true;
55821                         });
55822                         if (flag)
55823                             result.push(command);
55824                     });
55825                     return result;
55826                 };
55827             }
55828             filters.Tag = Tag;
55829         })(filters || (filters = {}));
55830         var app;
55831         (function (app) {
55832             'use strict';
55833             var appName = 'zephyr';
55834             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
55835             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
55836                 $urlRouterProvider.otherwise('/execution');
55837                 $locationProvider.html5Mode({
55838                     enabled: true,
55839                     requireBase: false
55840                 });
55841                 $stateProvider
55842                     .state('execution', {
55843                     url: '/execution',
55844                     templateUrl: 'templates/execution.html',
55845                     controller: 'executionController',
55846                     controllerAs: 'c'
55847                 })
55848                     .state('workspace', {
55849                     url: '/workspace',
55850                     templateUrl: 'templates/workspace.html',
55851                     controller: 'workspaceController',
55852                     controllerAs: 'c'
55853                 })
55854                     .state('history', {
55855                     url: '/history',
55856                     templateUrl: 'templates/history.html',
55857                     controller: 'historyController',
55858                     controllerAs: 'c'
55859                 });
55860             });
55861             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
55862             app.zephyr.service('MyModal', app.services.MyModal);
55863             app.zephyr.service('WebSocket', app.services.WebSocket);
55864             app.zephyr.service('Console', app.services.Console);
55865             app.zephyr.filter('Tag', filters.Tag);
55866             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
55867             app.zephyr.controller('previewController', app.controllers.Preview);
55868 <<<<<<< HEAD
55869             app.zephyr.controller('uploadController', app.controllers.Upload);
55870 =======
55871 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55872             app.zephyr.controller('executionController', app.controllers.Execution);
55873             app.zephyr.controller('workspaceController', app.controllers.Workspace);
55874             app.zephyr.controller('historyController', app.controllers.History);
55875             app.zephyr.controller('commandController', app.directives.CommandController);
55876             app.zephyr.controller('optionController', app.directives.OptionController);
55877             app.zephyr.controller('directoryController', app.directives.DirectoryController);
55878             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
55879 <<<<<<< HEAD
55880             app.zephyr.controller('uploadController', app.directives.UploadController);
55881 =======
55882 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55883             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
55884             app.zephyr.directive('command', app.directives.Command.Factory());
55885             app.zephyr.directive('option', app.directives.Option.Factory());
55886             app.zephyr.directive('directory', app.directives.Directory.Factory());
55887         })(app || (app = {}));
55888
55889
55890 /***/ },
55891 <<<<<<< HEAD
55892 /* 21 */
55893 =======
55894 /* 19 */
55895 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55896 /***/ function(module, exports) {
55897
55898         var app;
55899         (function (app) {
55900             var declares;
55901             (function (declares) {
55902                 var CommandInfo = (function () {
55903                     function CommandInfo(name) {
55904                         this.name = name;
55905                     }
55906                     return CommandInfo;
55907                 })();
55908                 declares.CommandInfo = CommandInfo;
55909             })(declares = app.declares || (app.declares = {}));
55910         })(app || (app = {}));
55911         var app;
55912         (function (app) {
55913             var services;
55914             (function (services) {
55915                 var APIEndPoint = (function () {
55916                     function APIEndPoint($resource, $http) {
55917                         this.$resource = $resource;
55918                         this.$http = $http;
55919                     }
55920                     APIEndPoint.prototype.resource = function (endPoint, data) {
55921                         var customAction = {
55922                             method: 'GET',
55923                             isArray: false
55924                         };
55925                         var execute = {
55926                             method: 'POST',
55927                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
55928                         };
55929                         return this.$resource(endPoint, {}, { execute: execute });
55930                     };
55931                     APIEndPoint.prototype.getOptionControlFile = function (command) {
55932                         var endPoint = '/api/v1/optionControlFile/' + command;
55933                         return this.resource(endPoint, {}).get();
55934                     };
55935                     APIEndPoint.prototype.getFiles = function (fileId) {
55936                         var endPoint = '/api/v1/workspace';
55937                         if (fileId) {
55938                             endPoint += '/' + fileId;
55939                         }
55940                         return this.resource(endPoint, {}).get();
55941                     };
55942                     APIEndPoint.prototype.getDirectories = function () {
55943                         var endPoint = '/api/v1/all/workspace/directory';
55944                         return this.resource(endPoint, {}).get();
55945                     };
55946                     APIEndPoint.prototype.getTags = function () {
55947                         var endPoint = '/api/v1/tagList';
55948                         return this.resource(endPoint, {}).get();
55949                     };
55950                     APIEndPoint.prototype.getCommands = function () {
55951                         var endPoint = '/api/v1/commandList';
55952                         return this.resource(endPoint, {}).get();
55953                     };
55954                     APIEndPoint.prototype.execute = function (data) {
55955                         var endPoint = '/api/v1/execution';
55956                         var fd = new FormData();
55957                         fd.append('data', data);
55958                         return this.$http.post(endPoint, fd, {
55959                             headers: { 'Content-Type': undefined },
55960                             transformRequest: angular.identity
55961                         });
55962                     };
55963                     APIEndPoint.prototype.debug = function () {
55964                         var endPoint = '/api/v1/debug';
55965                         return this.$http.get(endPoint);
55966                     };
55967 <<<<<<< HEAD
55968                     APIEndPoint.prototype.upload = function () {
55969                         var endPoint = '/api/v1/upload';
55970                         return this.$http.get(endPoint);
55971                     };
55972 =======
55973 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
55974                     APIEndPoint.prototype.help = function (command) {
55975                         var endPoint = '/api/v1/help/' + command;
55976                         return this.$http.get(endPoint);
55977                     };
55978                     return APIEndPoint;
55979                 })();
55980                 services.APIEndPoint = APIEndPoint;
55981             })(services = app.services || (app.services = {}));
55982         })(app || (app = {}));
55983         var app;
55984         (function (app) {
55985             var services;
55986             (function (services) {
55987                 var MyModal = (function () {
55988                     function MyModal($uibModal) {
55989                         this.$uibModal = $uibModal;
55990                         this.modalOption = {
55991                             backdrop: true,
55992                             controller: null,
55993                             templateUrl: null,
55994                             size: null
55995                         };
55996                     }
55997                     MyModal.prototype.open = function (modalName) {
55998                         if (modalName === 'SelectCommand') {
55999                             this.modalOption.templateUrl = 'templates/select-command.html';
56000                             this.modalOption.size = 'lg';
56001                         }
56002                         return this.$uibModal.open(this.modalOption);
56003                     };
56004                     MyModal.prototype.selectCommand = function () {
56005                         this.modalOption.templateUrl = 'templates/select-command.html';
56006                         this.modalOption.controller = 'selectCommandController';
56007                         this.modalOption.controllerAs = 'c';
56008                         this.modalOption.size = 'lg';
56009                         return this.$uibModal.open(this.modalOption);
56010                     };
56011                     MyModal.prototype.preview = function () {
56012                         this.modalOption.templateUrl = 'templates/preview.html';
56013                         this.modalOption.controller = 'previewController';
56014                         this.modalOption.controllerAs = 'c';
56015                         this.modalOption.size = 'lg';
56016                         return this.$uibModal.open(this.modalOption);
56017                     };
56018 <<<<<<< HEAD
56019                     MyModal.prototype.upload = function () {
56020                         this.modalOption.templateUrl = 'templates/upload.html';
56021                         this.modalOption.controller = 'uploadController';
56022                         this.modalOption.controllerAs = 'c';
56023                         this.modalOption.size = 'lg';
56024                         return this.$uibModal.open(this.modalOption);
56025                     };
56026 =======
56027 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56028                     MyModal.$inject = ['$uibModal'];
56029                     return MyModal;
56030                 })();
56031                 services.MyModal = MyModal;
56032             })(services = app.services || (app.services = {}));
56033         })(app || (app = {}));
56034         var app;
56035         (function (app) {
56036             var services;
56037             (function (services) {
56038                 var WebSocket = (function () {
56039                     function WebSocket($rootScope) {
56040                         this.$rootScope = $rootScope;
56041                         this.socket = io.connect();
56042                     }
56043                     WebSocket.prototype.on = function (eventName, callback) {
56044                         var socket = this.socket;
56045                         var rootScope = this.$rootScope;
56046                         socket.on(eventName, function () {
56047                             var args = arguments;
56048                             rootScope.$apply(function () {
56049                                 callback.apply(socket, args);
56050                             });
56051                         });
56052                     };
56053                     WebSocket.prototype.emit = function (eventName, data, callback) {
56054                         var socket = this.socket;
56055                         var rootScope = this.$rootScope;
56056                         this.socket.emit(eventName, data, function () {
56057                             var args = arguments;
56058                             rootScope.$apply(function () {
56059                                 if (callback)
56060                                     callback.apply(socket, args);
56061                             });
56062                         });
56063                     };
56064                     return WebSocket;
56065                 })();
56066                 services.WebSocket = WebSocket;
56067             })(services = app.services || (app.services = {}));
56068         })(app || (app = {}));
56069         var app;
56070         (function (app) {
56071             var services;
56072             (function (services) {
56073                 var Console = (function () {
56074                     function Console(WebSocket, $rootScope) {
56075                         this.WebSocket = WebSocket;
56076                         this.$rootScope = $rootScope;
56077                         this.WebSocket = WebSocket;
56078                         this.$rootScope = $rootScope;
56079                         this.directiveIDs = [];
56080                         var directiveIDs = this.directiveIDs;
56081                         this.WebSocket.on('console', function (d) {
56082                             var id = d.id;
56083                             var message = d.message;
56084                             if (directiveIDs.indexOf(id) > -1) {
56085                                 $rootScope.$emit(id, message);
56086                             }
56087                         });
56088                     }
56089                     Console.prototype.addDirective = function (id) {
56090                         if (!(this.directiveIDs.indexOf(id) > -1)) {
56091                             this.directiveIDs.push(id);
56092                         }
56093                     };
56094                     Console.prototype.removeDirective = function (id) {
56095                         var i = this.directiveIDs.indexOf(id);
56096                         if (i > -1) {
56097                             this.directiveIDs.splice(i, 1);
56098                         }
56099                     };
56100                     Console.prototype.showIDs = function () {
56101                         console.log(this.directiveIDs);
56102                     };
56103                     return Console;
56104                 })();
56105                 services.Console = Console;
56106             })(services = app.services || (app.services = {}));
56107         })(app || (app = {}));
56108         var app;
56109         (function (app) {
56110             var directives;
56111             (function (directives) {
56112                 var Command = (function () {
56113                     function Command() {
56114                         this.restrict = 'E';
56115                         this.replace = true;
56116                         this.scope = true;
56117                         this.controller = 'commandController';
56118                         this.controllerAs = 'ctrl';
56119                         this.bindToController = {
56120                             index: '=',
56121                             name: '=',
56122                             remove: '&',
56123                             list: '='
56124                         };
56125                         this.templateUrl = 'templates/command.html';
56126                     }
56127                     Command.Factory = function () {
56128                         var directive = function () {
56129                             return new Command();
56130                         };
56131                         directive.$inject = [];
56132                         return directive;
56133                     };
56134                     return Command;
56135                 })();
56136                 directives.Command = Command;
56137                 var CommandController = (function () {
56138                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
56139                         this.APIEndPoint = APIEndPoint;
56140                         this.$scope = $scope;
56141                         this.MyModal = MyModal;
56142                         this.WebSocket = WebSocket;
56143                         this.$window = $window;
56144                         this.$rootScope = $rootScope;
56145                         this.Console = Console;
56146                         var controller = this;
56147                         this.APIEndPoint
56148                             .getOptionControlFile(this.name)
56149                             .$promise
56150                             .then(function (result) {
56151                             controller.options = result.info;
56152                         });
56153                         this.APIEndPoint
56154                             .getDirectories()
56155                             .$promise
56156                             .then(function (result) {
56157                             controller.dirs = result.info;
56158                         });
56159                         this.heading = "[" + this.index + "]: dcdFilePrint";
56160                         this.isOpen = true;
56161                         this.$scope.$on('close', function () {
56162                             controller.isOpen = false;
56163                         });
56164                         function guid() {
56165                             function s4() {
56166                                 return Math.floor((1 + Math.random()) * 0x10000)
56167                                     .toString(16)
56168                                     .substring(1);
56169                             }
56170                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
56171                                 s4() + '-' + s4() + s4() + s4();
56172                         }
56173                         this.uuid = guid();
56174                         this.Console.addDirective(this.uuid);
56175                         this.Console.showIDs();
56176                     }
56177                     CommandController.prototype.submit = function () {
56178                         var opt = [];
56179                         angular.forEach(this.options, function (option) {
56180                             var obj = {
56181                                 name: option.option,
56182                                 arguments: []
56183                             };
56184                             angular.forEach(option.arg, function (arg) {
56185                                 if (arg.input) {
56186                                     if (typeof arg.input === 'object') {
56187                                         obj.arguments.push(arg.input.name);
56188                                     }
56189                                     else {
56190                                         obj.arguments.push(arg.input);
56191                                     }
56192                                 }
56193                             });
56194                             if (obj.arguments.length > 0) {
56195                                 opt.push(obj);
56196                             }
56197                         });
56198                         var execObj = {
56199                             command: this.name,
56200                             workspace: this.workspace.fileId,
56201                             options: opt
56202                         };
56203                         this.APIEndPoint
56204                             .execute(JSON.stringify(execObj))
56205                             .then(function (result) {
56206                             console.log(result);
56207                         });
56208                     };
56209                     CommandController.prototype.removeMySelf = function (index) {
56210                         this.$scope.$destroy();
56211                         this.Console.removeDirective(this.uuid);
56212                         this.remove()(index, this.list);
56213                         this.Console.showIDs();
56214                     };
56215                     CommandController.prototype.reloadFiles = function () {
56216                         var _this = this;
56217                         var fileId = this.workspace.fileId;
56218                         this.APIEndPoint
56219                             .getFiles(fileId)
56220                             .$promise
56221                             .then(function (result) {
56222                             var status = result.status;
56223                             if (status === 'success') {
56224                                 _this.files = result.info;
56225                             }
56226                             else {
56227                                 console.log(result.message);
56228                             }
56229                         });
56230                     };
56231                     CommandController.prototype.debug = function () {
56232                         var div = angular.element(this.$window.document).find("div");
56233                         var consoleTag;
56234                         var parametersTag;
56235                         angular.forEach(div, function (v) {
56236                             if (v.className === "panel-body console") {
56237                                 consoleTag = v;
56238                             }
56239                             else if (v.className === "row parameters-console") {
56240                                 parametersTag = v;
56241                             }
56242                         });
56243                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
56244                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
56245                         consoleTag.style.height = consoleHeight;
56246                         consoleTag.style.width = consoleWidth;
56247                     };
56248                     CommandController.prototype.help = function () {
56249                         this.APIEndPoint
56250                             .help(this.name)
56251                             .then(function (result) {
56252                             console.log(result);
56253                         });
56254                     };
56255                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
56256                     return CommandController;
56257                 })();
56258                 directives.CommandController = CommandController;
56259             })(directives = app.directives || (app.directives = {}));
56260         })(app || (app = {}));
56261         var app;
56262         (function (app) {
56263             var directives;
56264             (function (directives) {
56265                 var HeaderMenu = (function () {
56266                     function HeaderMenu() {
56267                         this.restrict = 'E';
56268                         this.replace = true;
56269                         this.templateUrl = 'templates/header-menu.html';
56270                         this.controller = 'HeaderMenuController';
56271                         this.controllerAs = 'hmc';
56272                         this.scope = true;
56273                     }
56274                     HeaderMenu.Factory = function () {
56275                         var directive = function () {
56276                             return new HeaderMenu();
56277                         };
56278                         return directive;
56279                     };
56280                     return HeaderMenu;
56281                 })();
56282                 directives.HeaderMenu = HeaderMenu;
56283                 var HeaderMenuController = (function () {
56284                     function HeaderMenuController($state) {
56285                         this.$state = $state;
56286                         this.isExecution = this.$state.current.name === 'execution';
56287                         this.isWorkspace = this.$state.current.name === 'workspace';
56288                         this.isHistory = this.$state.current.name === 'history';
56289                     }
56290                     HeaderMenuController.prototype.transit = function (state) {
56291                         this.$state.go(state);
56292                     };
56293                     HeaderMenuController.$inject = ['$state'];
56294                     return HeaderMenuController;
56295                 })();
56296                 directives.HeaderMenuController = HeaderMenuController;
56297             })(directives = app.directives || (app.directives = {}));
56298         })(app || (app = {}));
56299         var app;
56300         (function (app) {
56301             var directives;
56302             (function (directives) {
56303                 var Option = (function () {
56304                     function Option() {
56305                         this.restrict = 'E';
56306                         this.replace = true;
56307                         this.controller = 'optionController';
56308                         this.bindToController = {
56309                             info: '=',
56310                             files: '='
56311                         };
56312                         this.scope = true;
56313                         this.templateUrl = 'templates/option.html';
56314                         this.controllerAs = 'ctrl';
56315                     }
56316                     Option.Factory = function () {
56317                         var directive = function () {
56318                             return new Option();
56319                         };
56320                         directive.$inject = [];
56321                         return directive;
56322                     };
56323                     return Option;
56324                 })();
56325                 directives.Option = Option;
56326                 var OptionController = (function () {
56327                     function OptionController() {
56328                         var controller = this;
56329                         angular.forEach(controller.info.arg, function (arg) {
56330                             if (arg.initialValue) {
56331                                 if (arg.formType === 'number') {
56332                                     arg.input = parseInt(arg.initialValue);
56333                                 }
56334                                 else {
56335                                     arg.input = arg.initialValue;
56336                                 }
56337                             }
56338                         });
56339                     }
56340                     OptionController.$inject = [];
56341                     return OptionController;
56342                 })();
56343                 directives.OptionController = OptionController;
56344             })(directives = app.directives || (app.directives = {}));
56345         })(app || (app = {}));
56346         var app;
56347         (function (app) {
56348             var directives;
56349             (function (directives) {
56350                 var Directory = (function () {
56351                     function Directory() {
56352                         this.restrict = 'E';
56353                         this.replace = true;
56354                         this.controller = 'directoryController';
56355                         this.controllerAs = 'ctrl';
56356                         this.bindToController = {
56357                             info: '=',
56358                             add: '&',
56359                             list: '=',
56360                             files: '='
56361                         };
56362                         this.templateUrl = 'templates/directory.html';
56363                     }
56364                     Directory.Factory = function () {
56365                         var directive = function () {
56366                             return new Directory();
56367                         };
56368                         return directive;
56369                     };
56370                     return Directory;
56371                 })();
56372                 directives.Directory = Directory;
56373                 var DirectoryController = (function () {
56374                     function DirectoryController(APIEndPoint, $scope) {
56375                         this.APIEndPoint = APIEndPoint;
56376                         this.$scope = $scope;
56377                         var controller = this;
56378                         this.APIEndPoint
56379                             .getFiles(this.info.fileId)
56380                             .$promise
56381                             .then(function (result) {
56382                             if (result.status === 'success') {
56383                                 controller.files = result.info;
56384                                 angular.forEach(result.info, function (file) {
56385                                     if (file.fileType === '0') {
56386                                         var o = file;
56387                                         if (controller.info.path === '/') {
56388                                             o.path = '/' + file.name;
56389                                         }
56390                                         else {
56391                                             o.path = controller.info.path + '/' + file.name;
56392                                         }
56393                                         controller.add()(o, controller.list);
56394                                     }
56395                                 });
56396                             }
56397                             ;
56398                         });
56399                     }
56400                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
56401                     return DirectoryController;
56402                 })();
56403                 directives.DirectoryController = DirectoryController;
56404             })(directives = app.directives || (app.directives = {}));
56405         })(app || (app = {}));
56406         var app;
56407         (function (app) {
56408 <<<<<<< HEAD
56409             var directives;
56410             (function (directives) {
56411                 var Upload = (function () {
56412                     function Upload() {
56413                         this.restrict = 'E';
56414                         this.replace = true;
56415                         this.scope = true;
56416                         this.controller = 'UploadController';
56417                         this.controllerAs = 'ctrl';
56418                         this.bindToController = {
56419                             index: '=',
56420                             name: '=',
56421                             remove: '&',
56422                             list: '='
56423                         };
56424                         this.templateUrl = 'templates/upload.html';
56425                         console.log("templates/upload.html-constructor");
56426                     }
56427                     Upload.Factory = function () {
56428                         var directive = function () {
56429                             return new Upload();
56430                         };
56431                         directive.$inject = [];
56432                         return directive;
56433                     };
56434                     return Upload;
56435                 })();
56436                 directives.Upload = Upload;
56437                 var UploadController = (function () {
56438                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
56439                         this.APIEndPoint = APIEndPoint;
56440                         this.$scope = $scope;
56441                         this.MyModal = MyModal;
56442                         this.WebSocket = WebSocket;
56443                         this.$window = $window;
56444                         this.$rootScope = $rootScope;
56445                         this.Console = Console;
56446                         var controller = this;
56447                         console.log("directive.upload-constructor");
56448                     }
56449                     UploadController.prototype.submit = function () {
56450                         console.log("submit: function not supported¥n");
56451                     };
56452                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
56453                     return UploadController;
56454                 })();
56455                 directives.UploadController = UploadController;
56456             })(directives = app.directives || (app.directives = {}));
56457         })(app || (app = {}));
56458         var app;
56459         (function (app) {
56460 =======
56461 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56462             var controllers;
56463             (function (controllers) {
56464                 var Execution = (function () {
56465                     function Execution(MyModal, $scope) {
56466                         this.MyModal = MyModal;
56467                         this.$scope = $scope;
56468                         this.commandInfoList = [];
56469                     }
56470                     ;
56471                     Execution.prototype.add = function () {
56472                         this.$scope.$broadcast('close');
56473                         var commandInfoList = this.commandInfoList;
56474                         var commandInstance = this.MyModal.selectCommand();
56475                         commandInstance
56476                             .result
56477                             .then(function (command) {
56478                             commandInfoList.push(new app.declares.CommandInfo(command));
56479                         });
56480                     };
56481                     Execution.prototype.open = function () {
56482                         var result = this.MyModal.open('SelectCommand');
56483                         console.log(result);
56484                     };
56485                     Execution.prototype.remove = function (index, list) {
56486                         list.splice(index, 1);
56487                     };
56488                     Execution.prototype.close = function () {
56489                         console.log("close");
56490                     };
56491                     Execution.$inject = ['MyModal', '$scope'];
56492                     return Execution;
56493                 })();
56494                 controllers.Execution = Execution;
56495             })(controllers = app.controllers || (app.controllers = {}));
56496         })(app || (app = {}));
56497         var app;
56498         (function (app) {
56499             var controllers;
56500             (function (controllers) {
56501                 var Workspace = (function () {
56502                     function Workspace($scope, APIEndPoint, MyModal) {
56503                         this.$scope = $scope;
56504                         this.APIEndPoint = APIEndPoint;
56505                         this.MyModal = MyModal;
56506                         this.directoryList = [];
56507                         var controller = this;
56508                         var directoryList = this.directoryList;
56509                         var o = {
56510                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
56511                             name: '',
56512                             parentId: '',
56513                             fileType: '',
56514                             createdAt: '',
56515                             updatedAt: '',
56516                             path: '/'
56517                         };
56518                         directoryList.push(o);
56519                     }
56520                     Workspace.prototype.addDirectory = function (info, directoryList) {
56521                         directoryList.push(info);
56522                     };
56523 <<<<<<< HEAD
56524                     Workspace.prototype.upload = function () {
56525                         this.MyModal.upload();
56526                     };
56527 =======
56528 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56529                     Workspace.prototype.debug = function () {
56530                         this.MyModal.preview();
56531                     };
56532                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
56533                     return Workspace;
56534                 })();
56535                 controllers.Workspace = Workspace;
56536             })(controllers = app.controllers || (app.controllers = {}));
56537         })(app || (app = {}));
56538         var app;
56539         (function (app) {
56540             var controllers;
56541             (function (controllers) {
56542                 var History = (function () {
56543                     function History($scope) {
56544                         this.page = "History";
56545                     }
56546                     History.$inject = ['$scope'];
56547                     return History;
56548                 })();
56549                 controllers.History = History;
56550             })(controllers = app.controllers || (app.controllers = {}));
56551         })(app || (app = {}));
56552         var app;
56553         (function (app) {
56554             var controllers;
56555             (function (controllers) {
56556                 var SelectCommand = (function () {
56557                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
56558                         this.APIEndPoint = APIEndPoint;
56559                         this.$modalInstance = $modalInstance;
56560                         var controller = this;
56561                         this.APIEndPoint
56562                             .getTags()
56563                             .$promise.then(function (result) {
56564                             controller.tags = result.info;
56565                         });
56566                         this.APIEndPoint
56567                             .getCommands()
56568                             .$promise.then(function (result) {
56569                             controller.commands = result.info;
56570                         });
56571                         this.currentTag = 'all';
56572                     }
56573                     SelectCommand.prototype.changeTag = function (tag) {
56574                         this.currentTag = tag;
56575                     };
56576                     SelectCommand.prototype.selectCommand = function (command) {
56577                         this.$modalInstance.close(command);
56578                     };
56579                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
56580                     return SelectCommand;
56581                 })();
56582                 controllers.SelectCommand = SelectCommand;
56583             })(controllers = app.controllers || (app.controllers = {}));
56584         })(app || (app = {}));
56585         var app;
56586         (function (app) {
56587             var controllers;
56588             (function (controllers) {
56589 <<<<<<< HEAD
56590                 var Upload = (function () {
56591                     function Upload($scope, APIEndPoint, $modalInstance) {
56592                         this.APIEndPoint = APIEndPoint;
56593                         this.$modalInstance = $modalInstance;
56594                         var controller = this;
56595                         console.log('controller.upload-controllers');
56596                     }
56597                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
56598                     return Upload;
56599                 })();
56600                 controllers.Upload = Upload;
56601             })(controllers = app.controllers || (app.controllers = {}));
56602         })(app || (app = {}));
56603         var app;
56604         (function (app) {
56605             var controllers;
56606             (function (controllers) {
56607 =======
56608 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56609                 var Preview = (function () {
56610                     function Preview($scope, APIEndPoint, $modalInstance) {
56611                         this.APIEndPoint = APIEndPoint;
56612                         this.$modalInstance = $modalInstance;
56613                         var controller = this;
56614                         console.log('preview');
56615                     }
56616                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
56617                     return Preview;
56618                 })();
56619                 controllers.Preview = Preview;
56620             })(controllers = app.controllers || (app.controllers = {}));
56621         })(app || (app = {}));
56622         var filters;
56623         (function (filters) {
56624             function Tag() {
56625                 return function (commands, tag) {
56626                     var result = [];
56627                     angular.forEach(commands, function (command) {
56628                         var flag = false;
56629                         angular.forEach(command.tags, function (value) {
56630                             if (tag === value)
56631                                 flag = true;
56632                         });
56633                         if (flag)
56634                             result.push(command);
56635                     });
56636                     return result;
56637                 };
56638             }
56639             filters.Tag = Tag;
56640         })(filters || (filters = {}));
56641         var app;
56642         (function (app) {
56643             'use strict';
56644             var appName = 'zephyr';
56645             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
56646             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
56647                 $urlRouterProvider.otherwise('/execution');
56648                 $locationProvider.html5Mode({
56649                     enabled: true,
56650                     requireBase: false
56651                 });
56652                 $stateProvider
56653                     .state('execution', {
56654                     url: '/execution',
56655                     templateUrl: 'templates/execution.html',
56656                     controller: 'executionController',
56657                     controllerAs: 'c'
56658                 })
56659                     .state('workspace', {
56660                     url: '/workspace',
56661                     templateUrl: 'templates/workspace.html',
56662                     controller: 'workspaceController',
56663                     controllerAs: 'c'
56664                 })
56665                     .state('history', {
56666                     url: '/history',
56667                     templateUrl: 'templates/history.html',
56668                     controller: 'historyController',
56669                     controllerAs: 'c'
56670                 });
56671             });
56672             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
56673             app.zephyr.service('MyModal', app.services.MyModal);
56674             app.zephyr.service('WebSocket', app.services.WebSocket);
56675             app.zephyr.service('Console', app.services.Console);
56676             app.zephyr.filter('Tag', filters.Tag);
56677             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
56678             app.zephyr.controller('previewController', app.controllers.Preview);
56679 <<<<<<< HEAD
56680             app.zephyr.controller('uploadController', app.controllers.Upload);
56681 =======
56682 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56683             app.zephyr.controller('executionController', app.controllers.Execution);
56684             app.zephyr.controller('workspaceController', app.controllers.Workspace);
56685             app.zephyr.controller('historyController', app.controllers.History);
56686             app.zephyr.controller('commandController', app.directives.CommandController);
56687             app.zephyr.controller('optionController', app.directives.OptionController);
56688             app.zephyr.controller('directoryController', app.directives.DirectoryController);
56689             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
56690 <<<<<<< HEAD
56691             app.zephyr.controller('uploadController', app.directives.UploadController);
56692 =======
56693 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56694             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
56695             app.zephyr.directive('command', app.directives.Command.Factory());
56696             app.zephyr.directive('option', app.directives.Option.Factory());
56697             app.zephyr.directive('directory', app.directives.Directory.Factory());
56698         })(app || (app = {}));
56699
56700
56701 /***/ },
56702 <<<<<<< HEAD
56703 /* 22 */
56704 =======
56705 /* 20 */
56706 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56707 /***/ function(module, exports) {
56708
56709         var app;
56710         (function (app) {
56711             var declares;
56712             (function (declares) {
56713                 var CommandInfo = (function () {
56714                     function CommandInfo(name) {
56715                         this.name = name;
56716                     }
56717                     return CommandInfo;
56718                 })();
56719                 declares.CommandInfo = CommandInfo;
56720             })(declares = app.declares || (app.declares = {}));
56721         })(app || (app = {}));
56722         var app;
56723         (function (app) {
56724             var services;
56725             (function (services) {
56726                 var APIEndPoint = (function () {
56727                     function APIEndPoint($resource, $http) {
56728                         this.$resource = $resource;
56729                         this.$http = $http;
56730                     }
56731                     APIEndPoint.prototype.resource = function (endPoint, data) {
56732                         var customAction = {
56733                             method: 'GET',
56734                             isArray: false
56735                         };
56736                         var execute = {
56737                             method: 'POST',
56738                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
56739                         };
56740                         return this.$resource(endPoint, {}, { execute: execute });
56741                     };
56742                     APIEndPoint.prototype.getOptionControlFile = function (command) {
56743                         var endPoint = '/api/v1/optionControlFile/' + command;
56744                         return this.resource(endPoint, {}).get();
56745                     };
56746                     APIEndPoint.prototype.getFiles = function (fileId) {
56747                         var endPoint = '/api/v1/workspace';
56748                         if (fileId) {
56749                             endPoint += '/' + fileId;
56750                         }
56751                         return this.resource(endPoint, {}).get();
56752                     };
56753                     APIEndPoint.prototype.getDirectories = function () {
56754                         var endPoint = '/api/v1/all/workspace/directory';
56755                         return this.resource(endPoint, {}).get();
56756                     };
56757                     APIEndPoint.prototype.getTags = function () {
56758                         var endPoint = '/api/v1/tagList';
56759                         return this.resource(endPoint, {}).get();
56760                     };
56761                     APIEndPoint.prototype.getCommands = function () {
56762                         var endPoint = '/api/v1/commandList';
56763                         return this.resource(endPoint, {}).get();
56764                     };
56765                     APIEndPoint.prototype.execute = function (data) {
56766                         var endPoint = '/api/v1/execution';
56767                         var fd = new FormData();
56768                         fd.append('data', data);
56769                         return this.$http.post(endPoint, fd, {
56770                             headers: { 'Content-Type': undefined },
56771                             transformRequest: angular.identity
56772                         });
56773                     };
56774                     APIEndPoint.prototype.debug = function () {
56775                         var endPoint = '/api/v1/debug';
56776                         return this.$http.get(endPoint);
56777                     };
56778 <<<<<<< HEAD
56779                     APIEndPoint.prototype.upload = function () {
56780                         var endPoint = '/api/v1/upload';
56781                         return this.$http.get(endPoint);
56782                     };
56783 =======
56784 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56785                     APIEndPoint.prototype.help = function (command) {
56786                         var endPoint = '/api/v1/help/' + command;
56787                         return this.$http.get(endPoint);
56788                     };
56789                     return APIEndPoint;
56790                 })();
56791                 services.APIEndPoint = APIEndPoint;
56792             })(services = app.services || (app.services = {}));
56793         })(app || (app = {}));
56794         var app;
56795         (function (app) {
56796             var services;
56797             (function (services) {
56798                 var MyModal = (function () {
56799                     function MyModal($uibModal) {
56800                         this.$uibModal = $uibModal;
56801                         this.modalOption = {
56802                             backdrop: true,
56803                             controller: null,
56804                             templateUrl: null,
56805                             size: null
56806                         };
56807                     }
56808                     MyModal.prototype.open = function (modalName) {
56809                         if (modalName === 'SelectCommand') {
56810                             this.modalOption.templateUrl = 'templates/select-command.html';
56811                             this.modalOption.size = 'lg';
56812                         }
56813                         return this.$uibModal.open(this.modalOption);
56814                     };
56815                     MyModal.prototype.selectCommand = function () {
56816                         this.modalOption.templateUrl = 'templates/select-command.html';
56817                         this.modalOption.controller = 'selectCommandController';
56818                         this.modalOption.controllerAs = 'c';
56819                         this.modalOption.size = 'lg';
56820                         return this.$uibModal.open(this.modalOption);
56821                     };
56822                     MyModal.prototype.preview = function () {
56823                         this.modalOption.templateUrl = 'templates/preview.html';
56824                         this.modalOption.controller = 'previewController';
56825                         this.modalOption.controllerAs = 'c';
56826                         this.modalOption.size = 'lg';
56827                         return this.$uibModal.open(this.modalOption);
56828                     };
56829 <<<<<<< HEAD
56830                     MyModal.prototype.upload = function () {
56831                         this.modalOption.templateUrl = 'templates/upload.html';
56832                         this.modalOption.controller = 'uploadController';
56833                         this.modalOption.controllerAs = 'c';
56834                         this.modalOption.size = 'lg';
56835                         return this.$uibModal.open(this.modalOption);
56836                     };
56837 =======
56838 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
56839                     MyModal.$inject = ['$uibModal'];
56840                     return MyModal;
56841                 })();
56842                 services.MyModal = MyModal;
56843             })(services = app.services || (app.services = {}));
56844         })(app || (app = {}));
56845         var app;
56846         (function (app) {
56847             var services;
56848             (function (services) {
56849                 var WebSocket = (function () {
56850                     function WebSocket($rootScope) {
56851                         this.$rootScope = $rootScope;
56852                         this.socket = io.connect();
56853                     }
56854                     WebSocket.prototype.on = function (eventName, callback) {
56855                         var socket = this.socket;
56856                         var rootScope = this.$rootScope;
56857                         socket.on(eventName, function () {
56858                             var args = arguments;
56859                             rootScope.$apply(function () {
56860                                 callback.apply(socket, args);
56861                             });
56862                         });
56863                     };
56864                     WebSocket.prototype.emit = function (eventName, data, callback) {
56865                         var socket = this.socket;
56866                         var rootScope = this.$rootScope;
56867                         this.socket.emit(eventName, data, function () {
56868                             var args = arguments;
56869                             rootScope.$apply(function () {
56870                                 if (callback)
56871                                     callback.apply(socket, args);
56872                             });
56873                         });
56874                     };
56875                     return WebSocket;
56876                 })();
56877                 services.WebSocket = WebSocket;
56878             })(services = app.services || (app.services = {}));
56879         })(app || (app = {}));
56880         var app;
56881         (function (app) {
56882             var services;
56883             (function (services) {
56884                 var Console = (function () {
56885                     function Console(WebSocket, $rootScope) {
56886                         this.WebSocket = WebSocket;
56887                         this.$rootScope = $rootScope;
56888                         this.WebSocket = WebSocket;
56889                         this.$rootScope = $rootScope;
56890                         this.directiveIDs = [];
56891                         var directiveIDs = this.directiveIDs;
56892                         this.WebSocket.on('console', function (d) {
56893                             var id = d.id;
56894                             var message = d.message;
56895                             if (directiveIDs.indexOf(id) > -1) {
56896                                 $rootScope.$emit(id, message);
56897                             }
56898                         });
56899                     }
56900                     Console.prototype.addDirective = function (id) {
56901                         if (!(this.directiveIDs.indexOf(id) > -1)) {
56902                             this.directiveIDs.push(id);
56903                         }
56904                     };
56905                     Console.prototype.removeDirective = function (id) {
56906                         var i = this.directiveIDs.indexOf(id);
56907                         if (i > -1) {
56908                             this.directiveIDs.splice(i, 1);
56909                         }
56910                     };
56911                     Console.prototype.showIDs = function () {
56912                         console.log(this.directiveIDs);
56913                     };
56914                     return Console;
56915                 })();
56916                 services.Console = Console;
56917             })(services = app.services || (app.services = {}));
56918         })(app || (app = {}));
56919         var app;
56920         (function (app) {
56921             var directives;
56922             (function (directives) {
56923                 var Command = (function () {
56924                     function Command() {
56925                         this.restrict = 'E';
56926                         this.replace = true;
56927                         this.scope = true;
56928                         this.controller = 'commandController';
56929                         this.controllerAs = 'ctrl';
56930                         this.bindToController = {
56931                             index: '=',
56932                             name: '=',
56933                             remove: '&',
56934                             list: '='
56935                         };
56936                         this.templateUrl = 'templates/command.html';
56937                     }
56938                     Command.Factory = function () {
56939                         var directive = function () {
56940                             return new Command();
56941                         };
56942                         directive.$inject = [];
56943                         return directive;
56944                     };
56945                     return Command;
56946                 })();
56947                 directives.Command = Command;
56948                 var CommandController = (function () {
56949                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
56950                         this.APIEndPoint = APIEndPoint;
56951                         this.$scope = $scope;
56952                         this.MyModal = MyModal;
56953                         this.WebSocket = WebSocket;
56954                         this.$window = $window;
56955                         this.$rootScope = $rootScope;
56956                         this.Console = Console;
56957                         var controller = this;
56958                         this.APIEndPoint
56959                             .getOptionControlFile(this.name)
56960                             .$promise
56961                             .then(function (result) {
56962                             controller.options = result.info;
56963                         });
56964                         this.APIEndPoint
56965                             .getDirectories()
56966                             .$promise
56967                             .then(function (result) {
56968                             controller.dirs = result.info;
56969                         });
56970                         this.heading = "[" + this.index + "]: dcdFilePrint";
56971                         this.isOpen = true;
56972                         this.$scope.$on('close', function () {
56973                             controller.isOpen = false;
56974                         });
56975                         function guid() {
56976                             function s4() {
56977                                 return Math.floor((1 + Math.random()) * 0x10000)
56978                                     .toString(16)
56979                                     .substring(1);
56980                             }
56981                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
56982                                 s4() + '-' + s4() + s4() + s4();
56983                         }
56984                         this.uuid = guid();
56985                         this.Console.addDirective(this.uuid);
56986                         this.Console.showIDs();
56987                     }
56988                     CommandController.prototype.submit = function () {
56989                         var opt = [];
56990                         angular.forEach(this.options, function (option) {
56991                             var obj = {
56992                                 name: option.option,
56993                                 arguments: []
56994                             };
56995                             angular.forEach(option.arg, function (arg) {
56996                                 if (arg.input) {
56997                                     if (typeof arg.input === 'object') {
56998                                         obj.arguments.push(arg.input.name);
56999                                     }
57000                                     else {
57001                                         obj.arguments.push(arg.input);
57002                                     }
57003                                 }
57004                             });
57005                             if (obj.arguments.length > 0) {
57006                                 opt.push(obj);
57007                             }
57008                         });
57009                         var execObj = {
57010                             command: this.name,
57011                             workspace: this.workspace.fileId,
57012                             options: opt
57013                         };
57014                         this.APIEndPoint
57015                             .execute(JSON.stringify(execObj))
57016                             .then(function (result) {
57017                             console.log(result);
57018                         });
57019                     };
57020                     CommandController.prototype.removeMySelf = function (index) {
57021                         this.$scope.$destroy();
57022                         this.Console.removeDirective(this.uuid);
57023                         this.remove()(index, this.list);
57024                         this.Console.showIDs();
57025                     };
57026                     CommandController.prototype.reloadFiles = function () {
57027                         var _this = this;
57028                         var fileId = this.workspace.fileId;
57029                         this.APIEndPoint
57030                             .getFiles(fileId)
57031                             .$promise
57032                             .then(function (result) {
57033                             var status = result.status;
57034                             if (status === 'success') {
57035                                 _this.files = result.info;
57036                             }
57037                             else {
57038                                 console.log(result.message);
57039                             }
57040                         });
57041                     };
57042                     CommandController.prototype.debug = function () {
57043                         var div = angular.element(this.$window.document).find("div");
57044                         var consoleTag;
57045                         var parametersTag;
57046                         angular.forEach(div, function (v) {
57047                             if (v.className === "panel-body console") {
57048                                 consoleTag = v;
57049                             }
57050                             else if (v.className === "row parameters-console") {
57051                                 parametersTag = v;
57052                             }
57053                         });
57054                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
57055                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
57056                         consoleTag.style.height = consoleHeight;
57057                         consoleTag.style.width = consoleWidth;
57058                     };
57059                     CommandController.prototype.help = function () {
57060                         this.APIEndPoint
57061                             .help(this.name)
57062                             .then(function (result) {
57063                             console.log(result);
57064                         });
57065                     };
57066                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
57067                     return CommandController;
57068                 })();
57069                 directives.CommandController = CommandController;
57070             })(directives = app.directives || (app.directives = {}));
57071         })(app || (app = {}));
57072         var app;
57073         (function (app) {
57074             var directives;
57075             (function (directives) {
57076                 var HeaderMenu = (function () {
57077                     function HeaderMenu() {
57078                         this.restrict = 'E';
57079                         this.replace = true;
57080                         this.templateUrl = 'templates/header-menu.html';
57081                         this.controller = 'HeaderMenuController';
57082                         this.controllerAs = 'hmc';
57083                         this.scope = true;
57084                     }
57085                     HeaderMenu.Factory = function () {
57086                         var directive = function () {
57087                             return new HeaderMenu();
57088                         };
57089                         return directive;
57090                     };
57091                     return HeaderMenu;
57092                 })();
57093                 directives.HeaderMenu = HeaderMenu;
57094                 var HeaderMenuController = (function () {
57095                     function HeaderMenuController($state) {
57096                         this.$state = $state;
57097                         this.isExecution = this.$state.current.name === 'execution';
57098                         this.isWorkspace = this.$state.current.name === 'workspace';
57099                         this.isHistory = this.$state.current.name === 'history';
57100                     }
57101                     HeaderMenuController.prototype.transit = function (state) {
57102                         this.$state.go(state);
57103                     };
57104                     HeaderMenuController.$inject = ['$state'];
57105                     return HeaderMenuController;
57106                 })();
57107                 directives.HeaderMenuController = HeaderMenuController;
57108             })(directives = app.directives || (app.directives = {}));
57109         })(app || (app = {}));
57110         var app;
57111         (function (app) {
57112             var directives;
57113             (function (directives) {
57114                 var Option = (function () {
57115                     function Option() {
57116                         this.restrict = 'E';
57117                         this.replace = true;
57118                         this.controller = 'optionController';
57119                         this.bindToController = {
57120                             info: '=',
57121                             files: '='
57122                         };
57123                         this.scope = true;
57124                         this.templateUrl = 'templates/option.html';
57125                         this.controllerAs = 'ctrl';
57126                     }
57127                     Option.Factory = function () {
57128                         var directive = function () {
57129                             return new Option();
57130                         };
57131                         directive.$inject = [];
57132                         return directive;
57133                     };
57134                     return Option;
57135                 })();
57136                 directives.Option = Option;
57137                 var OptionController = (function () {
57138                     function OptionController() {
57139                         var controller = this;
57140                         angular.forEach(controller.info.arg, function (arg) {
57141                             if (arg.initialValue) {
57142                                 if (arg.formType === 'number') {
57143                                     arg.input = parseInt(arg.initialValue);
57144                                 }
57145                                 else {
57146                                     arg.input = arg.initialValue;
57147                                 }
57148                             }
57149                         });
57150                     }
57151                     OptionController.$inject = [];
57152                     return OptionController;
57153                 })();
57154                 directives.OptionController = OptionController;
57155             })(directives = app.directives || (app.directives = {}));
57156         })(app || (app = {}));
57157         var app;
57158         (function (app) {
57159             var directives;
57160             (function (directives) {
57161                 var Directory = (function () {
57162                     function Directory() {
57163                         this.restrict = 'E';
57164                         this.replace = true;
57165                         this.controller = 'directoryController';
57166                         this.controllerAs = 'ctrl';
57167                         this.bindToController = {
57168                             info: '=',
57169                             add: '&',
57170                             list: '=',
57171                             files: '='
57172                         };
57173                         this.templateUrl = 'templates/directory.html';
57174                     }
57175                     Directory.Factory = function () {
57176                         var directive = function () {
57177                             return new Directory();
57178                         };
57179                         return directive;
57180                     };
57181                     return Directory;
57182                 })();
57183                 directives.Directory = Directory;
57184                 var DirectoryController = (function () {
57185                     function DirectoryController(APIEndPoint, $scope) {
57186                         this.APIEndPoint = APIEndPoint;
57187                         this.$scope = $scope;
57188                         var controller = this;
57189                         this.APIEndPoint
57190                             .getFiles(this.info.fileId)
57191                             .$promise
57192                             .then(function (result) {
57193                             if (result.status === 'success') {
57194                                 controller.files = result.info;
57195                                 angular.forEach(result.info, function (file) {
57196                                     if (file.fileType === '0') {
57197                                         var o = file;
57198                                         if (controller.info.path === '/') {
57199                                             o.path = '/' + file.name;
57200                                         }
57201                                         else {
57202                                             o.path = controller.info.path + '/' + file.name;
57203                                         }
57204                                         controller.add()(o, controller.list);
57205                                     }
57206                                 });
57207                             }
57208                             ;
57209                         });
57210                     }
57211                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
57212                     return DirectoryController;
57213                 })();
57214                 directives.DirectoryController = DirectoryController;
57215             })(directives = app.directives || (app.directives = {}));
57216         })(app || (app = {}));
57217         var app;
57218         (function (app) {
57219 <<<<<<< HEAD
57220             var directives;
57221             (function (directives) {
57222                 var Upload = (function () {
57223                     function Upload() {
57224                         this.restrict = 'E';
57225                         this.replace = true;
57226                         this.scope = true;
57227                         this.controller = 'UploadController';
57228                         this.controllerAs = 'ctrl';
57229                         this.bindToController = {
57230                             index: '=',
57231                             name: '=',
57232                             remove: '&',
57233                             list: '='
57234                         };
57235                         this.templateUrl = 'templates/upload.html';
57236                         console.log("templates/upload.html-constructor");
57237                     }
57238                     Upload.Factory = function () {
57239                         var directive = function () {
57240                             return new Upload();
57241                         };
57242                         directive.$inject = [];
57243                         return directive;
57244                     };
57245                     return Upload;
57246                 })();
57247                 directives.Upload = Upload;
57248                 var UploadController = (function () {
57249                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
57250                         this.APIEndPoint = APIEndPoint;
57251                         this.$scope = $scope;
57252                         this.MyModal = MyModal;
57253                         this.WebSocket = WebSocket;
57254                         this.$window = $window;
57255                         this.$rootScope = $rootScope;
57256                         this.Console = Console;
57257                         var controller = this;
57258                         console.log("directive.upload-constructor");
57259                     }
57260                     UploadController.prototype.submit = function () {
57261                         console.log("submit: function not supported¥n");
57262                     };
57263                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
57264                     return UploadController;
57265                 })();
57266                 directives.UploadController = UploadController;
57267             })(directives = app.directives || (app.directives = {}));
57268         })(app || (app = {}));
57269         var app;
57270         (function (app) {
57271 =======
57272 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57273             var controllers;
57274             (function (controllers) {
57275                 var Execution = (function () {
57276                     function Execution(MyModal, $scope) {
57277                         this.MyModal = MyModal;
57278                         this.$scope = $scope;
57279                         this.commandInfoList = [];
57280                     }
57281                     ;
57282                     Execution.prototype.add = function () {
57283                         this.$scope.$broadcast('close');
57284                         var commandInfoList = this.commandInfoList;
57285                         var commandInstance = this.MyModal.selectCommand();
57286                         commandInstance
57287                             .result
57288                             .then(function (command) {
57289                             commandInfoList.push(new app.declares.CommandInfo(command));
57290                         });
57291                     };
57292                     Execution.prototype.open = function () {
57293                         var result = this.MyModal.open('SelectCommand');
57294                         console.log(result);
57295                     };
57296                     Execution.prototype.remove = function (index, list) {
57297                         list.splice(index, 1);
57298                     };
57299                     Execution.prototype.close = function () {
57300                         console.log("close");
57301                     };
57302                     Execution.$inject = ['MyModal', '$scope'];
57303                     return Execution;
57304                 })();
57305                 controllers.Execution = Execution;
57306             })(controllers = app.controllers || (app.controllers = {}));
57307         })(app || (app = {}));
57308         var app;
57309         (function (app) {
57310             var controllers;
57311             (function (controllers) {
57312                 var Workspace = (function () {
57313                     function Workspace($scope, APIEndPoint, MyModal) {
57314                         this.$scope = $scope;
57315                         this.APIEndPoint = APIEndPoint;
57316                         this.MyModal = MyModal;
57317                         this.directoryList = [];
57318                         var controller = this;
57319                         var directoryList = this.directoryList;
57320                         var o = {
57321                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
57322                             name: '',
57323                             parentId: '',
57324                             fileType: '',
57325                             createdAt: '',
57326                             updatedAt: '',
57327                             path: '/'
57328                         };
57329                         directoryList.push(o);
57330                     }
57331                     Workspace.prototype.addDirectory = function (info, directoryList) {
57332                         directoryList.push(info);
57333                     };
57334 <<<<<<< HEAD
57335                     Workspace.prototype.upload = function () {
57336                         this.MyModal.upload();
57337                     };
57338 =======
57339 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57340                     Workspace.prototype.debug = function () {
57341                         this.MyModal.preview();
57342                     };
57343                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
57344                     return Workspace;
57345                 })();
57346                 controllers.Workspace = Workspace;
57347             })(controllers = app.controllers || (app.controllers = {}));
57348         })(app || (app = {}));
57349         var app;
57350         (function (app) {
57351             var controllers;
57352             (function (controllers) {
57353                 var History = (function () {
57354                     function History($scope) {
57355                         this.page = "History";
57356                     }
57357                     History.$inject = ['$scope'];
57358                     return History;
57359                 })();
57360                 controllers.History = History;
57361             })(controllers = app.controllers || (app.controllers = {}));
57362         })(app || (app = {}));
57363         var app;
57364         (function (app) {
57365             var controllers;
57366             (function (controllers) {
57367                 var SelectCommand = (function () {
57368                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
57369                         this.APIEndPoint = APIEndPoint;
57370                         this.$modalInstance = $modalInstance;
57371                         var controller = this;
57372                         this.APIEndPoint
57373                             .getTags()
57374                             .$promise.then(function (result) {
57375                             controller.tags = result.info;
57376                         });
57377                         this.APIEndPoint
57378                             .getCommands()
57379                             .$promise.then(function (result) {
57380                             controller.commands = result.info;
57381                         });
57382                         this.currentTag = 'all';
57383                     }
57384                     SelectCommand.prototype.changeTag = function (tag) {
57385                         this.currentTag = tag;
57386                     };
57387                     SelectCommand.prototype.selectCommand = function (command) {
57388                         this.$modalInstance.close(command);
57389                     };
57390                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
57391                     return SelectCommand;
57392                 })();
57393                 controllers.SelectCommand = SelectCommand;
57394             })(controllers = app.controllers || (app.controllers = {}));
57395         })(app || (app = {}));
57396         var app;
57397         (function (app) {
57398             var controllers;
57399             (function (controllers) {
57400 <<<<<<< HEAD
57401                 var Upload = (function () {
57402                     function Upload($scope, APIEndPoint, $modalInstance) {
57403                         this.APIEndPoint = APIEndPoint;
57404                         this.$modalInstance = $modalInstance;
57405                         var controller = this;
57406                         console.log('controller.upload-controllers');
57407                     }
57408                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
57409                     return Upload;
57410                 })();
57411                 controllers.Upload = Upload;
57412             })(controllers = app.controllers || (app.controllers = {}));
57413         })(app || (app = {}));
57414         var app;
57415         (function (app) {
57416             var controllers;
57417             (function (controllers) {
57418 =======
57419 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57420                 var Preview = (function () {
57421                     function Preview($scope, APIEndPoint, $modalInstance) {
57422                         this.APIEndPoint = APIEndPoint;
57423                         this.$modalInstance = $modalInstance;
57424                         var controller = this;
57425                         console.log('preview');
57426                     }
57427                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
57428                     return Preview;
57429                 })();
57430                 controllers.Preview = Preview;
57431             })(controllers = app.controllers || (app.controllers = {}));
57432         })(app || (app = {}));
57433         var filters;
57434         (function (filters) {
57435             function Tag() {
57436                 return function (commands, tag) {
57437                     var result = [];
57438                     angular.forEach(commands, function (command) {
57439                         var flag = false;
57440                         angular.forEach(command.tags, function (value) {
57441                             if (tag === value)
57442                                 flag = true;
57443                         });
57444                         if (flag)
57445                             result.push(command);
57446                     });
57447                     return result;
57448                 };
57449             }
57450             filters.Tag = Tag;
57451         })(filters || (filters = {}));
57452         var app;
57453         (function (app) {
57454             'use strict';
57455             var appName = 'zephyr';
57456             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
57457             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
57458                 $urlRouterProvider.otherwise('/execution');
57459                 $locationProvider.html5Mode({
57460                     enabled: true,
57461                     requireBase: false
57462                 });
57463                 $stateProvider
57464                     .state('execution', {
57465                     url: '/execution',
57466                     templateUrl: 'templates/execution.html',
57467                     controller: 'executionController',
57468                     controllerAs: 'c'
57469                 })
57470                     .state('workspace', {
57471                     url: '/workspace',
57472                     templateUrl: 'templates/workspace.html',
57473                     controller: 'workspaceController',
57474                     controllerAs: 'c'
57475                 })
57476                     .state('history', {
57477                     url: '/history',
57478                     templateUrl: 'templates/history.html',
57479                     controller: 'historyController',
57480                     controllerAs: 'c'
57481                 });
57482             });
57483             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
57484             app.zephyr.service('MyModal', app.services.MyModal);
57485             app.zephyr.service('WebSocket', app.services.WebSocket);
57486             app.zephyr.service('Console', app.services.Console);
57487             app.zephyr.filter('Tag', filters.Tag);
57488             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
57489             app.zephyr.controller('previewController', app.controllers.Preview);
57490 <<<<<<< HEAD
57491             app.zephyr.controller('uploadController', app.controllers.Upload);
57492 =======
57493 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57494             app.zephyr.controller('executionController', app.controllers.Execution);
57495             app.zephyr.controller('workspaceController', app.controllers.Workspace);
57496             app.zephyr.controller('historyController', app.controllers.History);
57497             app.zephyr.controller('commandController', app.directives.CommandController);
57498             app.zephyr.controller('optionController', app.directives.OptionController);
57499             app.zephyr.controller('directoryController', app.directives.DirectoryController);
57500             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
57501 <<<<<<< HEAD
57502             app.zephyr.controller('uploadController', app.directives.UploadController);
57503 =======
57504 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57505             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
57506             app.zephyr.directive('command', app.directives.Command.Factory());
57507             app.zephyr.directive('option', app.directives.Option.Factory());
57508             app.zephyr.directive('directory', app.directives.Directory.Factory());
57509         })(app || (app = {}));
57510
57511
57512 /***/ },
57513 <<<<<<< HEAD
57514 /* 23 */
57515 =======
57516 /* 21 */
57517 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57518 /***/ function(module, exports) {
57519
57520         var app;
57521         (function (app) {
57522             var declares;
57523             (function (declares) {
57524                 var CommandInfo = (function () {
57525                     function CommandInfo(name) {
57526                         this.name = name;
57527                     }
57528                     return CommandInfo;
57529                 })();
57530                 declares.CommandInfo = CommandInfo;
57531             })(declares = app.declares || (app.declares = {}));
57532         })(app || (app = {}));
57533         var app;
57534         (function (app) {
57535             var services;
57536             (function (services) {
57537                 var APIEndPoint = (function () {
57538                     function APIEndPoint($resource, $http) {
57539                         this.$resource = $resource;
57540                         this.$http = $http;
57541                     }
57542                     APIEndPoint.prototype.resource = function (endPoint, data) {
57543                         var customAction = {
57544                             method: 'GET',
57545                             isArray: false
57546                         };
57547                         var execute = {
57548                             method: 'POST',
57549                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
57550                         };
57551                         return this.$resource(endPoint, {}, { execute: execute });
57552                     };
57553                     APIEndPoint.prototype.getOptionControlFile = function (command) {
57554                         var endPoint = '/api/v1/optionControlFile/' + command;
57555                         return this.resource(endPoint, {}).get();
57556                     };
57557                     APIEndPoint.prototype.getFiles = function (fileId) {
57558                         var endPoint = '/api/v1/workspace';
57559                         if (fileId) {
57560                             endPoint += '/' + fileId;
57561                         }
57562                         return this.resource(endPoint, {}).get();
57563                     };
57564                     APIEndPoint.prototype.getDirectories = function () {
57565                         var endPoint = '/api/v1/all/workspace/directory';
57566                         return this.resource(endPoint, {}).get();
57567                     };
57568                     APIEndPoint.prototype.getTags = function () {
57569                         var endPoint = '/api/v1/tagList';
57570                         return this.resource(endPoint, {}).get();
57571                     };
57572                     APIEndPoint.prototype.getCommands = function () {
57573                         var endPoint = '/api/v1/commandList';
57574                         return this.resource(endPoint, {}).get();
57575                     };
57576                     APIEndPoint.prototype.execute = function (data) {
57577                         var endPoint = '/api/v1/execution';
57578                         var fd = new FormData();
57579                         fd.append('data', data);
57580                         return this.$http.post(endPoint, fd, {
57581                             headers: { 'Content-Type': undefined },
57582                             transformRequest: angular.identity
57583                         });
57584                     };
57585                     APIEndPoint.prototype.debug = function () {
57586                         var endPoint = '/api/v1/debug';
57587                         return this.$http.get(endPoint);
57588                     };
57589 <<<<<<< HEAD
57590                     APIEndPoint.prototype.upload = function () {
57591                         var endPoint = '/api/v1/upload';
57592                         return this.$http.get(endPoint);
57593                     };
57594 =======
57595 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57596                     APIEndPoint.prototype.help = function (command) {
57597                         var endPoint = '/api/v1/help/' + command;
57598                         return this.$http.get(endPoint);
57599                     };
57600                     return APIEndPoint;
57601                 })();
57602                 services.APIEndPoint = APIEndPoint;
57603             })(services = app.services || (app.services = {}));
57604         })(app || (app = {}));
57605         var app;
57606         (function (app) {
57607             var services;
57608             (function (services) {
57609                 var MyModal = (function () {
57610                     function MyModal($uibModal) {
57611                         this.$uibModal = $uibModal;
57612                         this.modalOption = {
57613                             backdrop: true,
57614                             controller: null,
57615                             templateUrl: null,
57616                             size: null
57617                         };
57618                     }
57619                     MyModal.prototype.open = function (modalName) {
57620                         if (modalName === 'SelectCommand') {
57621                             this.modalOption.templateUrl = 'templates/select-command.html';
57622                             this.modalOption.size = 'lg';
57623                         }
57624                         return this.$uibModal.open(this.modalOption);
57625                     };
57626                     MyModal.prototype.selectCommand = function () {
57627                         this.modalOption.templateUrl = 'templates/select-command.html';
57628                         this.modalOption.controller = 'selectCommandController';
57629                         this.modalOption.controllerAs = 'c';
57630                         this.modalOption.size = 'lg';
57631                         return this.$uibModal.open(this.modalOption);
57632                     };
57633                     MyModal.prototype.preview = function () {
57634                         this.modalOption.templateUrl = 'templates/preview.html';
57635                         this.modalOption.controller = 'previewController';
57636                         this.modalOption.controllerAs = 'c';
57637                         this.modalOption.size = 'lg';
57638                         return this.$uibModal.open(this.modalOption);
57639                     };
57640 <<<<<<< HEAD
57641                     MyModal.prototype.upload = function () {
57642                         this.modalOption.templateUrl = 'templates/upload.html';
57643                         this.modalOption.controller = 'uploadController';
57644                         this.modalOption.controllerAs = 'c';
57645                         this.modalOption.size = 'lg';
57646                         return this.$uibModal.open(this.modalOption);
57647                     };
57648 =======
57649 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
57650                     MyModal.$inject = ['$uibModal'];
57651                     return MyModal;
57652                 })();
57653                 services.MyModal = MyModal;
57654             })(services = app.services || (app.services = {}));
57655         })(app || (app = {}));
57656         var app;
57657         (function (app) {
57658             var services;
57659             (function (services) {
57660                 var WebSocket = (function () {
57661                     function WebSocket($rootScope) {
57662                         this.$rootScope = $rootScope;
57663                         this.socket = io.connect();
57664                     }
57665                     WebSocket.prototype.on = function (eventName, callback) {
57666                         var socket = this.socket;
57667                         var rootScope = this.$rootScope;
57668                         socket.on(eventName, function () {
57669                             var args = arguments;
57670                             rootScope.$apply(function () {
57671                                 callback.apply(socket, args);
57672                             });
57673                         });
57674                     };
57675                     WebSocket.prototype.emit = function (eventName, data, callback) {
57676                         var socket = this.socket;
57677                         var rootScope = this.$rootScope;
57678                         this.socket.emit(eventName, data, function () {
57679                             var args = arguments;
57680                             rootScope.$apply(function () {
57681                                 if (callback)
57682                                     callback.apply(socket, args);
57683                             });
57684                         });
57685                     };
57686                     return WebSocket;
57687                 })();
57688                 services.WebSocket = WebSocket;
57689             })(services = app.services || (app.services = {}));
57690         })(app || (app = {}));
57691         var app;
57692         (function (app) {
57693             var services;
57694             (function (services) {
57695                 var Console = (function () {
57696                     function Console(WebSocket, $rootScope) {
57697                         this.WebSocket = WebSocket;
57698                         this.$rootScope = $rootScope;
57699                         this.WebSocket = WebSocket;
57700                         this.$rootScope = $rootScope;
57701                         this.directiveIDs = [];
57702                         var directiveIDs = this.directiveIDs;
57703                         this.WebSocket.on('console', function (d) {
57704                             var id = d.id;
57705                             var message = d.message;
57706                             if (directiveIDs.indexOf(id) > -1) {
57707                                 $rootScope.$emit(id, message);
57708                             }
57709                         });
57710                     }
57711                     Console.prototype.addDirective = function (id) {
57712                         if (!(this.directiveIDs.indexOf(id) > -1)) {
57713                             this.directiveIDs.push(id);
57714                         }
57715                     };
57716                     Console.prototype.removeDirective = function (id) {
57717                         var i = this.directiveIDs.indexOf(id);
57718                         if (i > -1) {
57719                             this.directiveIDs.splice(i, 1);
57720                         }
57721                     };
57722                     Console.prototype.showIDs = function () {
57723                         console.log(this.directiveIDs);
57724                     };
57725                     return Console;
57726                 })();
57727                 services.Console = Console;
57728             })(services = app.services || (app.services = {}));
57729         })(app || (app = {}));
57730         var app;
57731         (function (app) {
57732             var directives;
57733             (function (directives) {
57734                 var Command = (function () {
57735                     function Command() {
57736                         this.restrict = 'E';
57737                         this.replace = true;
57738                         this.scope = true;
57739                         this.controller = 'commandController';
57740                         this.controllerAs = 'ctrl';
57741                         this.bindToController = {
57742                             index: '=',
57743                             name: '=',
57744                             remove: '&',
57745                             list: '='
57746                         };
57747                         this.templateUrl = 'templates/command.html';
57748                     }
57749                     Command.Factory = function () {
57750                         var directive = function () {
57751                             return new Command();
57752                         };
57753                         directive.$inject = [];
57754                         return directive;
57755                     };
57756                     return Command;
57757                 })();
57758                 directives.Command = Command;
57759                 var CommandController = (function () {
57760                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
57761                         this.APIEndPoint = APIEndPoint;
57762                         this.$scope = $scope;
57763                         this.MyModal = MyModal;
57764                         this.WebSocket = WebSocket;
57765                         this.$window = $window;
57766                         this.$rootScope = $rootScope;
57767                         this.Console = Console;
57768                         var controller = this;
57769                         this.APIEndPoint
57770                             .getOptionControlFile(this.name)
57771                             .$promise
57772                             .then(function (result) {
57773                             controller.options = result.info;
57774                         });
57775                         this.APIEndPoint
57776                             .getDirectories()
57777                             .$promise
57778                             .then(function (result) {
57779                             controller.dirs = result.info;
57780                         });
57781                         this.heading = "[" + this.index + "]: dcdFilePrint";
57782                         this.isOpen = true;
57783                         this.$scope.$on('close', function () {
57784                             controller.isOpen = false;
57785                         });
57786                         function guid() {
57787                             function s4() {
57788                                 return Math.floor((1 + Math.random()) * 0x10000)
57789                                     .toString(16)
57790                                     .substring(1);
57791                             }
57792                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
57793                                 s4() + '-' + s4() + s4() + s4();
57794                         }
57795                         this.uuid = guid();
57796                         this.Console.addDirective(this.uuid);
57797                         this.Console.showIDs();
57798                     }
57799                     CommandController.prototype.submit = function () {
57800                         var opt = [];
57801                         angular.forEach(this.options, function (option) {
57802                             var obj = {
57803                                 name: option.option,
57804                                 arguments: []
57805                             };
57806                             angular.forEach(option.arg, function (arg) {
57807                                 if (arg.input) {
57808                                     if (typeof arg.input === 'object') {
57809                                         obj.arguments.push(arg.input.name);
57810                                     }
57811                                     else {
57812                                         obj.arguments.push(arg.input);
57813                                     }
57814                                 }
57815                             });
57816                             if (obj.arguments.length > 0) {
57817                                 opt.push(obj);
57818                             }
57819                         });
57820                         var execObj = {
57821                             command: this.name,
57822                             workspace: this.workspace.fileId,
57823                             options: opt
57824                         };
57825                         this.APIEndPoint
57826                             .execute(JSON.stringify(execObj))
57827                             .then(function (result) {
57828                             console.log(result);
57829                         });
57830                     };
57831                     CommandController.prototype.removeMySelf = function (index) {
57832                         this.$scope.$destroy();
57833                         this.Console.removeDirective(this.uuid);
57834                         this.remove()(index, this.list);
57835                         this.Console.showIDs();
57836                     };
57837                     CommandController.prototype.reloadFiles = function () {
57838                         var _this = this;
57839                         var fileId = this.workspace.fileId;
57840                         this.APIEndPoint
57841                             .getFiles(fileId)
57842                             .$promise
57843                             .then(function (result) {
57844                             var status = result.status;
57845                             if (status === 'success') {
57846                                 _this.files = result.info;
57847                             }
57848                             else {
57849                                 console.log(result.message);
57850                             }
57851                         });
57852                     };
57853                     CommandController.prototype.debug = function () {
57854                         var div = angular.element(this.$window.document).find("div");
57855                         var consoleTag;
57856                         var parametersTag;
57857                         angular.forEach(div, function (v) {
57858                             if (v.className === "panel-body console") {
57859                                 consoleTag = v;
57860                             }
57861                             else if (v.className === "row parameters-console") {
57862                                 parametersTag = v;
57863                             }
57864                         });
57865                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
57866                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
57867                         consoleTag.style.height = consoleHeight;
57868                         consoleTag.style.width = consoleWidth;
57869                     };
57870                     CommandController.prototype.help = function () {
57871                         this.APIEndPoint
57872                             .help(this.name)
57873                             .then(function (result) {
57874                             console.log(result);
57875                         });
57876                     };
57877                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
57878                     return CommandController;
57879                 })();
57880                 directives.CommandController = CommandController;
57881             })(directives = app.directives || (app.directives = {}));
57882         })(app || (app = {}));
57883         var app;
57884         (function (app) {
57885             var directives;
57886             (function (directives) {
57887                 var HeaderMenu = (function () {
57888                     function HeaderMenu() {
57889                         this.restrict = 'E';
57890                         this.replace = true;
57891                         this.templateUrl = 'templates/header-menu.html';
57892                         this.controller = 'HeaderMenuController';
57893                         this.controllerAs = 'hmc';
57894                         this.scope = true;
57895                     }
57896                     HeaderMenu.Factory = function () {
57897                         var directive = function () {
57898                             return new HeaderMenu();
57899                         };
57900                         return directive;
57901                     };
57902                     return HeaderMenu;
57903                 })();
57904                 directives.HeaderMenu = HeaderMenu;
57905                 var HeaderMenuController = (function () {
57906                     function HeaderMenuController($state) {
57907                         this.$state = $state;
57908                         this.isExecution = this.$state.current.name === 'execution';
57909                         this.isWorkspace = this.$state.current.name === 'workspace';
57910                         this.isHistory = this.$state.current.name === 'history';
57911                     }
57912                     HeaderMenuController.prototype.transit = function (state) {
57913                         this.$state.go(state);
57914                     };
57915                     HeaderMenuController.$inject = ['$state'];
57916                     return HeaderMenuController;
57917                 })();
57918                 directives.HeaderMenuController = HeaderMenuController;
57919             })(directives = app.directives || (app.directives = {}));
57920         })(app || (app = {}));
57921         var app;
57922         (function (app) {
57923             var directives;
57924             (function (directives) {
57925                 var Option = (function () {
57926                     function Option() {
57927                         this.restrict = 'E';
57928                         this.replace = true;
57929                         this.controller = 'optionController';
57930                         this.bindToController = {
57931                             info: '=',
57932                             files: '='
57933                         };
57934                         this.scope = true;
57935                         this.templateUrl = 'templates/option.html';
57936                         this.controllerAs = 'ctrl';
57937                     }
57938                     Option.Factory = function () {
57939                         var directive = function () {
57940                             return new Option();
57941                         };
57942                         directive.$inject = [];
57943                         return directive;
57944                     };
57945                     return Option;
57946                 })();
57947                 directives.Option = Option;
57948                 var OptionController = (function () {
57949                     function OptionController() {
57950                         var controller = this;
57951                         angular.forEach(controller.info.arg, function (arg) {
57952                             if (arg.initialValue) {
57953                                 if (arg.formType === 'number') {
57954                                     arg.input = parseInt(arg.initialValue);
57955                                 }
57956                                 else {
57957                                     arg.input = arg.initialValue;
57958                                 }
57959                             }
57960                         });
57961                     }
57962                     OptionController.$inject = [];
57963                     return OptionController;
57964                 })();
57965                 directives.OptionController = OptionController;
57966             })(directives = app.directives || (app.directives = {}));
57967         })(app || (app = {}));
57968         var app;
57969         (function (app) {
57970             var directives;
57971             (function (directives) {
57972                 var Directory = (function () {
57973                     function Directory() {
57974                         this.restrict = 'E';
57975                         this.replace = true;
57976                         this.controller = 'directoryController';
57977                         this.controllerAs = 'ctrl';
57978                         this.bindToController = {
57979                             info: '=',
57980                             add: '&',
57981                             list: '=',
57982                             files: '='
57983                         };
57984                         this.templateUrl = 'templates/directory.html';
57985                     }
57986                     Directory.Factory = function () {
57987                         var directive = function () {
57988                             return new Directory();
57989                         };
57990                         return directive;
57991                     };
57992                     return Directory;
57993                 })();
57994                 directives.Directory = Directory;
57995                 var DirectoryController = (function () {
57996                     function DirectoryController(APIEndPoint, $scope) {
57997                         this.APIEndPoint = APIEndPoint;
57998                         this.$scope = $scope;
57999                         var controller = this;
58000                         this.APIEndPoint
58001                             .getFiles(this.info.fileId)
58002                             .$promise
58003                             .then(function (result) {
58004                             if (result.status === 'success') {
58005                                 controller.files = result.info;
58006                                 angular.forEach(result.info, function (file) {
58007                                     if (file.fileType === '0') {
58008                                         var o = file;
58009                                         if (controller.info.path === '/') {
58010                                             o.path = '/' + file.name;
58011                                         }
58012                                         else {
58013                                             o.path = controller.info.path + '/' + file.name;
58014                                         }
58015                                         controller.add()(o, controller.list);
58016                                     }
58017                                 });
58018                             }
58019                             ;
58020                         });
58021                     }
58022                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
58023                     return DirectoryController;
58024                 })();
58025                 directives.DirectoryController = DirectoryController;
58026             })(directives = app.directives || (app.directives = {}));
58027         })(app || (app = {}));
58028         var app;
58029         (function (app) {
58030 <<<<<<< HEAD
58031             var directives;
58032             (function (directives) {
58033                 var Upload = (function () {
58034                     function Upload() {
58035                         this.restrict = 'E';
58036                         this.replace = true;
58037                         this.scope = true;
58038                         this.controller = 'UploadController';
58039                         this.controllerAs = 'ctrl';
58040                         this.bindToController = {
58041                             index: '=',
58042                             name: '=',
58043                             remove: '&',
58044                             list: '='
58045                         };
58046                         this.templateUrl = 'templates/upload.html';
58047                         console.log("templates/upload.html-constructor");
58048                     }
58049                     Upload.Factory = function () {
58050                         var directive = function () {
58051                             return new Upload();
58052                         };
58053                         directive.$inject = [];
58054                         return directive;
58055                     };
58056                     return Upload;
58057                 })();
58058                 directives.Upload = Upload;
58059                 var UploadController = (function () {
58060                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
58061                         this.APIEndPoint = APIEndPoint;
58062                         this.$scope = $scope;
58063                         this.MyModal = MyModal;
58064                         this.WebSocket = WebSocket;
58065                         this.$window = $window;
58066                         this.$rootScope = $rootScope;
58067                         this.Console = Console;
58068                         var controller = this;
58069                         console.log("directive.upload-constructor");
58070                     }
58071                     UploadController.prototype.submit = function () {
58072                         console.log("submit: function not supported¥n");
58073                     };
58074                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
58075                     return UploadController;
58076                 })();
58077                 directives.UploadController = UploadController;
58078             })(directives = app.directives || (app.directives = {}));
58079         })(app || (app = {}));
58080         var app;
58081         (function (app) {
58082 =======
58083 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58084             var controllers;
58085             (function (controllers) {
58086                 var Execution = (function () {
58087                     function Execution(MyModal, $scope) {
58088                         this.MyModal = MyModal;
58089                         this.$scope = $scope;
58090                         this.commandInfoList = [];
58091                     }
58092                     ;
58093                     Execution.prototype.add = function () {
58094                         this.$scope.$broadcast('close');
58095                         var commandInfoList = this.commandInfoList;
58096                         var commandInstance = this.MyModal.selectCommand();
58097                         commandInstance
58098                             .result
58099                             .then(function (command) {
58100                             commandInfoList.push(new app.declares.CommandInfo(command));
58101                         });
58102                     };
58103                     Execution.prototype.open = function () {
58104                         var result = this.MyModal.open('SelectCommand');
58105                         console.log(result);
58106                     };
58107                     Execution.prototype.remove = function (index, list) {
58108                         list.splice(index, 1);
58109                     };
58110                     Execution.prototype.close = function () {
58111                         console.log("close");
58112                     };
58113                     Execution.$inject = ['MyModal', '$scope'];
58114                     return Execution;
58115                 })();
58116                 controllers.Execution = Execution;
58117             })(controllers = app.controllers || (app.controllers = {}));
58118         })(app || (app = {}));
58119         var app;
58120         (function (app) {
58121             var controllers;
58122             (function (controllers) {
58123                 var Workspace = (function () {
58124                     function Workspace($scope, APIEndPoint, MyModal) {
58125                         this.$scope = $scope;
58126                         this.APIEndPoint = APIEndPoint;
58127                         this.MyModal = MyModal;
58128                         this.directoryList = [];
58129                         var controller = this;
58130                         var directoryList = this.directoryList;
58131                         var o = {
58132                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
58133                             name: '',
58134                             parentId: '',
58135                             fileType: '',
58136                             createdAt: '',
58137                             updatedAt: '',
58138                             path: '/'
58139                         };
58140                         directoryList.push(o);
58141                     }
58142                     Workspace.prototype.addDirectory = function (info, directoryList) {
58143                         directoryList.push(info);
58144                     };
58145 <<<<<<< HEAD
58146                     Workspace.prototype.upload = function () {
58147                         this.MyModal.upload();
58148                     };
58149 =======
58150 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58151                     Workspace.prototype.debug = function () {
58152                         this.MyModal.preview();
58153                     };
58154                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
58155                     return Workspace;
58156                 })();
58157                 controllers.Workspace = Workspace;
58158             })(controllers = app.controllers || (app.controllers = {}));
58159         })(app || (app = {}));
58160         var app;
58161         (function (app) {
58162             var controllers;
58163             (function (controllers) {
58164                 var History = (function () {
58165                     function History($scope) {
58166                         this.page = "History";
58167                     }
58168                     History.$inject = ['$scope'];
58169                     return History;
58170                 })();
58171                 controllers.History = History;
58172             })(controllers = app.controllers || (app.controllers = {}));
58173         })(app || (app = {}));
58174         var app;
58175         (function (app) {
58176             var controllers;
58177             (function (controllers) {
58178                 var SelectCommand = (function () {
58179                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
58180                         this.APIEndPoint = APIEndPoint;
58181                         this.$modalInstance = $modalInstance;
58182                         var controller = this;
58183                         this.APIEndPoint
58184                             .getTags()
58185                             .$promise.then(function (result) {
58186                             controller.tags = result.info;
58187                         });
58188                         this.APIEndPoint
58189                             .getCommands()
58190                             .$promise.then(function (result) {
58191                             controller.commands = result.info;
58192                         });
58193                         this.currentTag = 'all';
58194                     }
58195                     SelectCommand.prototype.changeTag = function (tag) {
58196                         this.currentTag = tag;
58197                     };
58198                     SelectCommand.prototype.selectCommand = function (command) {
58199                         this.$modalInstance.close(command);
58200                     };
58201                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
58202                     return SelectCommand;
58203                 })();
58204                 controllers.SelectCommand = SelectCommand;
58205             })(controllers = app.controllers || (app.controllers = {}));
58206         })(app || (app = {}));
58207         var app;
58208         (function (app) {
58209             var controllers;
58210             (function (controllers) {
58211 <<<<<<< HEAD
58212                 var Upload = (function () {
58213                     function Upload($scope, APIEndPoint, $modalInstance) {
58214                         this.APIEndPoint = APIEndPoint;
58215                         this.$modalInstance = $modalInstance;
58216                         var controller = this;
58217                         console.log('controller.upload-controllers');
58218                     }
58219                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
58220                     return Upload;
58221                 })();
58222                 controllers.Upload = Upload;
58223             })(controllers = app.controllers || (app.controllers = {}));
58224         })(app || (app = {}));
58225         var app;
58226         (function (app) {
58227             var controllers;
58228             (function (controllers) {
58229 =======
58230 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58231                 var Preview = (function () {
58232                     function Preview($scope, APIEndPoint, $modalInstance) {
58233                         this.APIEndPoint = APIEndPoint;
58234                         this.$modalInstance = $modalInstance;
58235                         var controller = this;
58236                         console.log('preview');
58237                     }
58238                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
58239                     return Preview;
58240                 })();
58241                 controllers.Preview = Preview;
58242             })(controllers = app.controllers || (app.controllers = {}));
58243         })(app || (app = {}));
58244         var filters;
58245         (function (filters) {
58246             function Tag() {
58247                 return function (commands, tag) {
58248                     var result = [];
58249                     angular.forEach(commands, function (command) {
58250                         var flag = false;
58251                         angular.forEach(command.tags, function (value) {
58252                             if (tag === value)
58253                                 flag = true;
58254                         });
58255                         if (flag)
58256                             result.push(command);
58257                     });
58258                     return result;
58259                 };
58260             }
58261             filters.Tag = Tag;
58262         })(filters || (filters = {}));
58263         var app;
58264         (function (app) {
58265             'use strict';
58266             var appName = 'zephyr';
58267             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
58268             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
58269                 $urlRouterProvider.otherwise('/execution');
58270                 $locationProvider.html5Mode({
58271                     enabled: true,
58272                     requireBase: false
58273                 });
58274                 $stateProvider
58275                     .state('execution', {
58276                     url: '/execution',
58277                     templateUrl: 'templates/execution.html',
58278                     controller: 'executionController',
58279                     controllerAs: 'c'
58280                 })
58281                     .state('workspace', {
58282                     url: '/workspace',
58283                     templateUrl: 'templates/workspace.html',
58284                     controller: 'workspaceController',
58285                     controllerAs: 'c'
58286                 })
58287                     .state('history', {
58288                     url: '/history',
58289                     templateUrl: 'templates/history.html',
58290                     controller: 'historyController',
58291                     controllerAs: 'c'
58292                 });
58293             });
58294             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
58295             app.zephyr.service('MyModal', app.services.MyModal);
58296             app.zephyr.service('WebSocket', app.services.WebSocket);
58297             app.zephyr.service('Console', app.services.Console);
58298             app.zephyr.filter('Tag', filters.Tag);
58299             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
58300             app.zephyr.controller('previewController', app.controllers.Preview);
58301 <<<<<<< HEAD
58302             app.zephyr.controller('uploadController', app.controllers.Upload);
58303 =======
58304 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58305             app.zephyr.controller('executionController', app.controllers.Execution);
58306             app.zephyr.controller('workspaceController', app.controllers.Workspace);
58307             app.zephyr.controller('historyController', app.controllers.History);
58308             app.zephyr.controller('commandController', app.directives.CommandController);
58309             app.zephyr.controller('optionController', app.directives.OptionController);
58310             app.zephyr.controller('directoryController', app.directives.DirectoryController);
58311             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
58312 <<<<<<< HEAD
58313             app.zephyr.controller('uploadController', app.directives.UploadController);
58314 =======
58315 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58316             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
58317             app.zephyr.directive('command', app.directives.Command.Factory());
58318             app.zephyr.directive('option', app.directives.Option.Factory());
58319             app.zephyr.directive('directory', app.directives.Directory.Factory());
58320         })(app || (app = {}));
58321
58322
58323 /***/ },
58324 <<<<<<< HEAD
58325 /* 24 */
58326 =======
58327 /* 22 */
58328 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58329 /***/ function(module, exports) {
58330
58331         var app;
58332         (function (app) {
58333             var declares;
58334             (function (declares) {
58335                 var CommandInfo = (function () {
58336                     function CommandInfo(name) {
58337                         this.name = name;
58338                     }
58339                     return CommandInfo;
58340                 })();
58341                 declares.CommandInfo = CommandInfo;
58342             })(declares = app.declares || (app.declares = {}));
58343         })(app || (app = {}));
58344         var app;
58345         (function (app) {
58346             var services;
58347             (function (services) {
58348                 var APIEndPoint = (function () {
58349                     function APIEndPoint($resource, $http) {
58350                         this.$resource = $resource;
58351                         this.$http = $http;
58352                     }
58353                     APIEndPoint.prototype.resource = function (endPoint, data) {
58354                         var customAction = {
58355                             method: 'GET',
58356                             isArray: false
58357                         };
58358                         var execute = {
58359                             method: 'POST',
58360                             headers: { 'Content-Type': undefined, enctype: 'multipart/form-data' }
58361                         };
58362                         return this.$resource(endPoint, {}, { execute: execute });
58363                     };
58364                     APIEndPoint.prototype.getOptionControlFile = function (command) {
58365                         var endPoint = '/api/v1/optionControlFile/' + command;
58366                         return this.resource(endPoint, {}).get();
58367                     };
58368                     APIEndPoint.prototype.getFiles = function (fileId) {
58369                         var endPoint = '/api/v1/workspace';
58370                         if (fileId) {
58371                             endPoint += '/' + fileId;
58372                         }
58373                         return this.resource(endPoint, {}).get();
58374                     };
58375                     APIEndPoint.prototype.getDirectories = function () {
58376                         var endPoint = '/api/v1/all/workspace/directory';
58377                         return this.resource(endPoint, {}).get();
58378                     };
58379                     APIEndPoint.prototype.getTags = function () {
58380                         var endPoint = '/api/v1/tagList';
58381                         return this.resource(endPoint, {}).get();
58382                     };
58383                     APIEndPoint.prototype.getCommands = function () {
58384                         var endPoint = '/api/v1/commandList';
58385                         return this.resource(endPoint, {}).get();
58386                     };
58387                     APIEndPoint.prototype.execute = function (data) {
58388                         var endPoint = '/api/v1/execution';
58389                         var fd = new FormData();
58390                         fd.append('data', data);
58391                         return this.$http.post(endPoint, fd, {
58392                             headers: { 'Content-Type': undefined },
58393                             transformRequest: angular.identity
58394                         });
58395                     };
58396                     APIEndPoint.prototype.debug = function () {
58397                         var endPoint = '/api/v1/debug';
58398                         return this.$http.get(endPoint);
58399                     };
58400 <<<<<<< HEAD
58401                     APIEndPoint.prototype.upload = function () {
58402                         var endPoint = '/api/v1/upload';
58403                         return this.$http.get(endPoint);
58404                     };
58405 =======
58406 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58407                     APIEndPoint.prototype.help = function (command) {
58408                         var endPoint = '/api/v1/help/' + command;
58409                         return this.$http.get(endPoint);
58410                     };
58411                     return APIEndPoint;
58412                 })();
58413                 services.APIEndPoint = APIEndPoint;
58414             })(services = app.services || (app.services = {}));
58415         })(app || (app = {}));
58416         var app;
58417         (function (app) {
58418             var services;
58419             (function (services) {
58420                 var MyModal = (function () {
58421                     function MyModal($uibModal) {
58422                         this.$uibModal = $uibModal;
58423                         this.modalOption = {
58424                             backdrop: true,
58425                             controller: null,
58426                             templateUrl: null,
58427                             size: null
58428                         };
58429                     }
58430                     MyModal.prototype.open = function (modalName) {
58431                         if (modalName === 'SelectCommand') {
58432                             this.modalOption.templateUrl = 'templates/select-command.html';
58433                             this.modalOption.size = 'lg';
58434                         }
58435                         return this.$uibModal.open(this.modalOption);
58436                     };
58437                     MyModal.prototype.selectCommand = function () {
58438                         this.modalOption.templateUrl = 'templates/select-command.html';
58439                         this.modalOption.controller = 'selectCommandController';
58440                         this.modalOption.controllerAs = 'c';
58441                         this.modalOption.size = 'lg';
58442                         return this.$uibModal.open(this.modalOption);
58443                     };
58444                     MyModal.prototype.preview = function () {
58445                         this.modalOption.templateUrl = 'templates/preview.html';
58446                         this.modalOption.controller = 'previewController';
58447                         this.modalOption.controllerAs = 'c';
58448                         this.modalOption.size = 'lg';
58449                         return this.$uibModal.open(this.modalOption);
58450                     };
58451 <<<<<<< HEAD
58452                     MyModal.prototype.upload = function () {
58453                         this.modalOption.templateUrl = 'templates/upload.html';
58454                         this.modalOption.controller = 'uploadController';
58455                         this.modalOption.controllerAs = 'c';
58456                         this.modalOption.size = 'lg';
58457                         return this.$uibModal.open(this.modalOption);
58458                     };
58459 =======
58460 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58461                     MyModal.$inject = ['$uibModal'];
58462                     return MyModal;
58463                 })();
58464                 services.MyModal = MyModal;
58465             })(services = app.services || (app.services = {}));
58466         })(app || (app = {}));
58467         var app;
58468         (function (app) {
58469             var services;
58470             (function (services) {
58471                 var WebSocket = (function () {
58472                     function WebSocket($rootScope) {
58473                         this.$rootScope = $rootScope;
58474                         this.socket = io.connect();
58475                     }
58476                     WebSocket.prototype.on = function (eventName, callback) {
58477                         var socket = this.socket;
58478                         var rootScope = this.$rootScope;
58479                         socket.on(eventName, function () {
58480                             var args = arguments;
58481                             rootScope.$apply(function () {
58482                                 callback.apply(socket, args);
58483                             });
58484                         });
58485                     };
58486                     WebSocket.prototype.emit = function (eventName, data, callback) {
58487                         var socket = this.socket;
58488                         var rootScope = this.$rootScope;
58489                         this.socket.emit(eventName, data, function () {
58490                             var args = arguments;
58491                             rootScope.$apply(function () {
58492                                 if (callback)
58493                                     callback.apply(socket, args);
58494                             });
58495                         });
58496                     };
58497                     return WebSocket;
58498                 })();
58499                 services.WebSocket = WebSocket;
58500             })(services = app.services || (app.services = {}));
58501         })(app || (app = {}));
58502         var app;
58503         (function (app) {
58504             var services;
58505             (function (services) {
58506                 var Console = (function () {
58507                     function Console(WebSocket, $rootScope) {
58508                         this.WebSocket = WebSocket;
58509                         this.$rootScope = $rootScope;
58510                         this.WebSocket = WebSocket;
58511                         this.$rootScope = $rootScope;
58512                         this.directiveIDs = [];
58513                         var directiveIDs = this.directiveIDs;
58514                         this.WebSocket.on('console', function (d) {
58515                             var id = d.id;
58516                             var message = d.message;
58517                             if (directiveIDs.indexOf(id) > -1) {
58518                                 $rootScope.$emit(id, message);
58519                             }
58520                         });
58521                     }
58522                     Console.prototype.addDirective = function (id) {
58523                         if (!(this.directiveIDs.indexOf(id) > -1)) {
58524                             this.directiveIDs.push(id);
58525                         }
58526                     };
58527                     Console.prototype.removeDirective = function (id) {
58528                         var i = this.directiveIDs.indexOf(id);
58529                         if (i > -1) {
58530                             this.directiveIDs.splice(i, 1);
58531                         }
58532                     };
58533                     Console.prototype.showIDs = function () {
58534                         console.log(this.directiveIDs);
58535                     };
58536                     return Console;
58537                 })();
58538                 services.Console = Console;
58539             })(services = app.services || (app.services = {}));
58540         })(app || (app = {}));
58541         var app;
58542         (function (app) {
58543             var directives;
58544             (function (directives) {
58545                 var Command = (function () {
58546                     function Command() {
58547                         this.restrict = 'E';
58548                         this.replace = true;
58549                         this.scope = true;
58550                         this.controller = 'commandController';
58551                         this.controllerAs = 'ctrl';
58552                         this.bindToController = {
58553                             index: '=',
58554                             name: '=',
58555                             remove: '&',
58556                             list: '='
58557                         };
58558                         this.templateUrl = 'templates/command.html';
58559                     }
58560                     Command.Factory = function () {
58561                         var directive = function () {
58562                             return new Command();
58563                         };
58564                         directive.$inject = [];
58565                         return directive;
58566                     };
58567                     return Command;
58568                 })();
58569                 directives.Command = Command;
58570                 var CommandController = (function () {
58571                     function CommandController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
58572                         this.APIEndPoint = APIEndPoint;
58573                         this.$scope = $scope;
58574                         this.MyModal = MyModal;
58575                         this.WebSocket = WebSocket;
58576                         this.$window = $window;
58577                         this.$rootScope = $rootScope;
58578                         this.Console = Console;
58579                         var controller = this;
58580                         this.APIEndPoint
58581                             .getOptionControlFile(this.name)
58582                             .$promise
58583                             .then(function (result) {
58584                             controller.options = result.info;
58585                         });
58586                         this.APIEndPoint
58587                             .getDirectories()
58588                             .$promise
58589                             .then(function (result) {
58590                             controller.dirs = result.info;
58591                         });
58592                         this.heading = "[" + this.index + "]: dcdFilePrint";
58593                         this.isOpen = true;
58594                         this.$scope.$on('close', function () {
58595                             controller.isOpen = false;
58596                         });
58597                         function guid() {
58598                             function s4() {
58599                                 return Math.floor((1 + Math.random()) * 0x10000)
58600                                     .toString(16)
58601                                     .substring(1);
58602                             }
58603                             return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
58604                                 s4() + '-' + s4() + s4() + s4();
58605                         }
58606                         this.uuid = guid();
58607                         this.Console.addDirective(this.uuid);
58608                         this.Console.showIDs();
58609                     }
58610                     CommandController.prototype.submit = function () {
58611                         var opt = [];
58612                         angular.forEach(this.options, function (option) {
58613                             var obj = {
58614                                 name: option.option,
58615                                 arguments: []
58616                             };
58617                             angular.forEach(option.arg, function (arg) {
58618                                 if (arg.input) {
58619                                     if (typeof arg.input === 'object') {
58620                                         obj.arguments.push(arg.input.name);
58621                                     }
58622                                     else {
58623                                         obj.arguments.push(arg.input);
58624                                     }
58625                                 }
58626                             });
58627                             if (obj.arguments.length > 0) {
58628                                 opt.push(obj);
58629                             }
58630                         });
58631                         var execObj = {
58632                             command: this.name,
58633                             workspace: this.workspace.fileId,
58634                             options: opt
58635                         };
58636                         this.APIEndPoint
58637                             .execute(JSON.stringify(execObj))
58638                             .then(function (result) {
58639                             console.log(result);
58640                         });
58641                     };
58642                     CommandController.prototype.removeMySelf = function (index) {
58643                         this.$scope.$destroy();
58644                         this.Console.removeDirective(this.uuid);
58645                         this.remove()(index, this.list);
58646                         this.Console.showIDs();
58647                     };
58648                     CommandController.prototype.reloadFiles = function () {
58649                         var _this = this;
58650                         var fileId = this.workspace.fileId;
58651                         this.APIEndPoint
58652                             .getFiles(fileId)
58653                             .$promise
58654                             .then(function (result) {
58655                             var status = result.status;
58656                             if (status === 'success') {
58657                                 _this.files = result.info;
58658                             }
58659                             else {
58660                                 console.log(result.message);
58661                             }
58662                         });
58663                     };
58664                     CommandController.prototype.debug = function () {
58665                         var div = angular.element(this.$window.document).find("div");
58666                         var consoleTag;
58667                         var parametersTag;
58668                         angular.forEach(div, function (v) {
58669                             if (v.className === "panel-body console") {
58670                                 consoleTag = v;
58671                             }
58672                             else if (v.className === "row parameters-console") {
58673                                 parametersTag = v;
58674                             }
58675                         });
58676                         var consoleHeight = parseInt(parametersTag.clientHeight.toString().replace('px', '')) - 150 + 'px';
58677                         var consoleWidth = parseInt(parametersTag.clientWidth.toString().replace('px', '')) / 3 * 2 - 150 + 'px';
58678                         consoleTag.style.height = consoleHeight;
58679                         consoleTag.style.width = consoleWidth;
58680                     };
58681                     CommandController.prototype.help = function () {
58682                         this.APIEndPoint
58683                             .help(this.name)
58684                             .then(function (result) {
58685                             console.log(result);
58686                         });
58687                     };
58688                     CommandController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
58689                     return CommandController;
58690                 })();
58691                 directives.CommandController = CommandController;
58692             })(directives = app.directives || (app.directives = {}));
58693         })(app || (app = {}));
58694         var app;
58695         (function (app) {
58696             var directives;
58697             (function (directives) {
58698                 var HeaderMenu = (function () {
58699                     function HeaderMenu() {
58700                         this.restrict = 'E';
58701                         this.replace = true;
58702                         this.templateUrl = 'templates/header-menu.html';
58703                         this.controller = 'HeaderMenuController';
58704                         this.controllerAs = 'hmc';
58705                         this.scope = true;
58706                     }
58707                     HeaderMenu.Factory = function () {
58708                         var directive = function () {
58709                             return new HeaderMenu();
58710                         };
58711                         return directive;
58712                     };
58713                     return HeaderMenu;
58714                 })();
58715                 directives.HeaderMenu = HeaderMenu;
58716                 var HeaderMenuController = (function () {
58717                     function HeaderMenuController($state) {
58718                         this.$state = $state;
58719                         this.isExecution = this.$state.current.name === 'execution';
58720                         this.isWorkspace = this.$state.current.name === 'workspace';
58721                         this.isHistory = this.$state.current.name === 'history';
58722                     }
58723                     HeaderMenuController.prototype.transit = function (state) {
58724                         this.$state.go(state);
58725                     };
58726                     HeaderMenuController.$inject = ['$state'];
58727                     return HeaderMenuController;
58728                 })();
58729                 directives.HeaderMenuController = HeaderMenuController;
58730             })(directives = app.directives || (app.directives = {}));
58731         })(app || (app = {}));
58732         var app;
58733         (function (app) {
58734             var directives;
58735             (function (directives) {
58736                 var Option = (function () {
58737                     function Option() {
58738                         this.restrict = 'E';
58739                         this.replace = true;
58740                         this.controller = 'optionController';
58741                         this.bindToController = {
58742                             info: '=',
58743                             files: '='
58744                         };
58745                         this.scope = true;
58746                         this.templateUrl = 'templates/option.html';
58747                         this.controllerAs = 'ctrl';
58748                     }
58749                     Option.Factory = function () {
58750                         var directive = function () {
58751                             return new Option();
58752                         };
58753                         directive.$inject = [];
58754                         return directive;
58755                     };
58756                     return Option;
58757                 })();
58758                 directives.Option = Option;
58759                 var OptionController = (function () {
58760                     function OptionController() {
58761                         var controller = this;
58762                         angular.forEach(controller.info.arg, function (arg) {
58763                             if (arg.initialValue) {
58764                                 if (arg.formType === 'number') {
58765                                     arg.input = parseInt(arg.initialValue);
58766                                 }
58767                                 else {
58768                                     arg.input = arg.initialValue;
58769                                 }
58770                             }
58771                         });
58772                     }
58773                     OptionController.$inject = [];
58774                     return OptionController;
58775                 })();
58776                 directives.OptionController = OptionController;
58777             })(directives = app.directives || (app.directives = {}));
58778         })(app || (app = {}));
58779         var app;
58780         (function (app) {
58781             var directives;
58782             (function (directives) {
58783                 var Directory = (function () {
58784                     function Directory() {
58785                         this.restrict = 'E';
58786                         this.replace = true;
58787                         this.controller = 'directoryController';
58788                         this.controllerAs = 'ctrl';
58789                         this.bindToController = {
58790                             info: '=',
58791                             add: '&',
58792                             list: '=',
58793                             files: '='
58794                         };
58795                         this.templateUrl = 'templates/directory.html';
58796                     }
58797                     Directory.Factory = function () {
58798                         var directive = function () {
58799                             return new Directory();
58800                         };
58801                         return directive;
58802                     };
58803                     return Directory;
58804                 })();
58805                 directives.Directory = Directory;
58806                 var DirectoryController = (function () {
58807                     function DirectoryController(APIEndPoint, $scope) {
58808                         this.APIEndPoint = APIEndPoint;
58809                         this.$scope = $scope;
58810                         var controller = this;
58811                         this.APIEndPoint
58812                             .getFiles(this.info.fileId)
58813                             .$promise
58814                             .then(function (result) {
58815                             if (result.status === 'success') {
58816                                 controller.files = result.info;
58817                                 angular.forEach(result.info, function (file) {
58818                                     if (file.fileType === '0') {
58819                                         var o = file;
58820                                         if (controller.info.path === '/') {
58821                                             o.path = '/' + file.name;
58822                                         }
58823                                         else {
58824                                             o.path = controller.info.path + '/' + file.name;
58825                                         }
58826                                         controller.add()(o, controller.list);
58827                                     }
58828                                 });
58829                             }
58830                             ;
58831                         });
58832                     }
58833                     DirectoryController.$inject = ['APIEndPoint', '$scope'];
58834                     return DirectoryController;
58835                 })();
58836                 directives.DirectoryController = DirectoryController;
58837             })(directives = app.directives || (app.directives = {}));
58838         })(app || (app = {}));
58839         var app;
58840         (function (app) {
58841 <<<<<<< HEAD
58842             var directives;
58843             (function (directives) {
58844                 var Upload = (function () {
58845                     function Upload() {
58846                         this.restrict = 'E';
58847                         this.replace = true;
58848                         this.scope = true;
58849                         this.controller = 'UploadController';
58850                         this.controllerAs = 'ctrl';
58851                         this.bindToController = {
58852                             index: '=',
58853                             name: '=',
58854                             remove: '&',
58855                             list: '='
58856                         };
58857                         this.templateUrl = 'templates/upload.html';
58858                         console.log("templates/upload.html-constructor");
58859                     }
58860                     Upload.Factory = function () {
58861                         var directive = function () {
58862                             return new Upload();
58863                         };
58864                         directive.$inject = [];
58865                         return directive;
58866                     };
58867                     return Upload;
58868                 })();
58869                 directives.Upload = Upload;
58870                 var UploadController = (function () {
58871                     function UploadController(APIEndPoint, $scope, MyModal, WebSocket, $window, $rootScope, Console) {
58872                         this.APIEndPoint = APIEndPoint;
58873                         this.$scope = $scope;
58874                         this.MyModal = MyModal;
58875                         this.WebSocket = WebSocket;
58876                         this.$window = $window;
58877                         this.$rootScope = $rootScope;
58878                         this.Console = Console;
58879                         var controller = this;
58880                         console.log("directive.upload-constructor");
58881                     }
58882                     UploadController.prototype.submit = function () {
58883                         console.log("submit: function not supported¥n");
58884                     };
58885                     UploadController.$inject = ['APIEndPoint', '$scope', 'MyModal', 'WebSocket', '$window', '$rootScope', 'Console'];
58886                     return UploadController;
58887                 })();
58888                 directives.UploadController = UploadController;
58889             })(directives = app.directives || (app.directives = {}));
58890         })(app || (app = {}));
58891         var app;
58892         (function (app) {
58893 =======
58894 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58895             var controllers;
58896             (function (controllers) {
58897                 var Execution = (function () {
58898                     function Execution(MyModal, $scope) {
58899                         this.MyModal = MyModal;
58900                         this.$scope = $scope;
58901                         this.commandInfoList = [];
58902                     }
58903                     ;
58904                     Execution.prototype.add = function () {
58905                         this.$scope.$broadcast('close');
58906                         var commandInfoList = this.commandInfoList;
58907                         var commandInstance = this.MyModal.selectCommand();
58908                         commandInstance
58909                             .result
58910                             .then(function (command) {
58911                             commandInfoList.push(new app.declares.CommandInfo(command));
58912                         });
58913                     };
58914                     Execution.prototype.open = function () {
58915                         var result = this.MyModal.open('SelectCommand');
58916                         console.log(result);
58917                     };
58918                     Execution.prototype.remove = function (index, list) {
58919                         list.splice(index, 1);
58920                     };
58921                     Execution.prototype.close = function () {
58922                         console.log("close");
58923                     };
58924                     Execution.$inject = ['MyModal', '$scope'];
58925                     return Execution;
58926                 })();
58927                 controllers.Execution = Execution;
58928             })(controllers = app.controllers || (app.controllers = {}));
58929         })(app || (app = {}));
58930         var app;
58931         (function (app) {
58932             var controllers;
58933             (function (controllers) {
58934                 var Workspace = (function () {
58935                     function Workspace($scope, APIEndPoint, MyModal) {
58936                         this.$scope = $scope;
58937                         this.APIEndPoint = APIEndPoint;
58938                         this.MyModal = MyModal;
58939                         this.directoryList = [];
58940                         var controller = this;
58941                         var directoryList = this.directoryList;
58942                         var o = {
58943                             fileId: '1f83f620-c1ed-11e5-9657-7942989daa00',
58944                             name: '',
58945                             parentId: '',
58946                             fileType: '',
58947                             createdAt: '',
58948                             updatedAt: '',
58949                             path: '/'
58950                         };
58951                         directoryList.push(o);
58952                     }
58953                     Workspace.prototype.addDirectory = function (info, directoryList) {
58954                         directoryList.push(info);
58955                     };
58956 <<<<<<< HEAD
58957                     Workspace.prototype.upload = function () {
58958                         this.MyModal.upload();
58959                     };
58960 =======
58961 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
58962                     Workspace.prototype.debug = function () {
58963                         this.MyModal.preview();
58964                     };
58965                     Workspace.$inject = ['$scope', 'APIEndPoint', 'MyModal'];
58966                     return Workspace;
58967                 })();
58968                 controllers.Workspace = Workspace;
58969             })(controllers = app.controllers || (app.controllers = {}));
58970         })(app || (app = {}));
58971         var app;
58972         (function (app) {
58973             var controllers;
58974             (function (controllers) {
58975                 var History = (function () {
58976                     function History($scope) {
58977                         this.page = "History";
58978                     }
58979                     History.$inject = ['$scope'];
58980                     return History;
58981                 })();
58982                 controllers.History = History;
58983             })(controllers = app.controllers || (app.controllers = {}));
58984         })(app || (app = {}));
58985         var app;
58986         (function (app) {
58987             var controllers;
58988             (function (controllers) {
58989                 var SelectCommand = (function () {
58990                     function SelectCommand($scope, APIEndPoint, $modalInstance) {
58991                         this.APIEndPoint = APIEndPoint;
58992                         this.$modalInstance = $modalInstance;
58993                         var controller = this;
58994                         this.APIEndPoint
58995                             .getTags()
58996                             .$promise.then(function (result) {
58997                             controller.tags = result.info;
58998                         });
58999                         this.APIEndPoint
59000                             .getCommands()
59001                             .$promise.then(function (result) {
59002                             controller.commands = result.info;
59003                         });
59004                         this.currentTag = 'all';
59005                     }
59006                     SelectCommand.prototype.changeTag = function (tag) {
59007                         this.currentTag = tag;
59008                     };
59009                     SelectCommand.prototype.selectCommand = function (command) {
59010                         this.$modalInstance.close(command);
59011                     };
59012                     SelectCommand.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
59013                     return SelectCommand;
59014                 })();
59015                 controllers.SelectCommand = SelectCommand;
59016             })(controllers = app.controllers || (app.controllers = {}));
59017         })(app || (app = {}));
59018         var app;
59019         (function (app) {
59020             var controllers;
59021             (function (controllers) {
59022 <<<<<<< HEAD
59023                 var Upload = (function () {
59024                     function Upload($scope, APIEndPoint, $modalInstance) {
59025                         this.APIEndPoint = APIEndPoint;
59026                         this.$modalInstance = $modalInstance;
59027                         var controller = this;
59028                         console.log('controller.upload-controllers');
59029                     }
59030                     Upload.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
59031                     return Upload;
59032                 })();
59033                 controllers.Upload = Upload;
59034             })(controllers = app.controllers || (app.controllers = {}));
59035         })(app || (app = {}));
59036         var app;
59037         (function (app) {
59038             var controllers;
59039             (function (controllers) {
59040 =======
59041 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
59042                 var Preview = (function () {
59043                     function Preview($scope, APIEndPoint, $modalInstance) {
59044                         this.APIEndPoint = APIEndPoint;
59045                         this.$modalInstance = $modalInstance;
59046                         var controller = this;
59047                         console.log('preview');
59048                     }
59049                     Preview.$inject = ['$scope', 'APIEndPoint', '$uibModalInstance'];
59050                     return Preview;
59051                 })();
59052                 controllers.Preview = Preview;
59053             })(controllers = app.controllers || (app.controllers = {}));
59054         })(app || (app = {}));
59055         var filters;
59056         (function (filters) {
59057             function Tag() {
59058                 return function (commands, tag) {
59059                     var result = [];
59060                     angular.forEach(commands, function (command) {
59061                         var flag = false;
59062                         angular.forEach(command.tags, function (value) {
59063                             if (tag === value)
59064                                 flag = true;
59065                         });
59066                         if (flag)
59067                             result.push(command);
59068                     });
59069                     return result;
59070                 };
59071             }
59072             filters.Tag = Tag;
59073         })(filters || (filters = {}));
59074         var app;
59075         (function (app) {
59076             'use strict';
59077             var appName = 'zephyr';
59078             app.zephyr = angular.module(appName, ['ui.router', 'ngResource', 'ui.bootstrap']);
59079             app.zephyr.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
59080                 $urlRouterProvider.otherwise('/execution');
59081                 $locationProvider.html5Mode({
59082                     enabled: true,
59083                     requireBase: false
59084                 });
59085                 $stateProvider
59086                     .state('execution', {
59087                     url: '/execution',
59088                     templateUrl: 'templates/execution.html',
59089                     controller: 'executionController',
59090                     controllerAs: 'c'
59091                 })
59092                     .state('workspace', {
59093                     url: '/workspace',
59094                     templateUrl: 'templates/workspace.html',
59095                     controller: 'workspaceController',
59096                     controllerAs: 'c'
59097                 })
59098                     .state('history', {
59099                     url: '/history',
59100                     templateUrl: 'templates/history.html',
59101                     controller: 'historyController',
59102                     controllerAs: 'c'
59103                 });
59104             });
59105             app.zephyr.service('APIEndPoint', app.services.APIEndPoint);
59106             app.zephyr.service('MyModal', app.services.MyModal);
59107             app.zephyr.service('WebSocket', app.services.WebSocket);
59108             app.zephyr.service('Console', app.services.Console);
59109             app.zephyr.filter('Tag', filters.Tag);
59110             app.zephyr.controller('selectCommandController', app.controllers.SelectCommand);
59111             app.zephyr.controller('previewController', app.controllers.Preview);
59112 <<<<<<< HEAD
59113             app.zephyr.controller('uploadController', app.controllers.Upload);
59114 =======
59115 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
59116             app.zephyr.controller('executionController', app.controllers.Execution);
59117             app.zephyr.controller('workspaceController', app.controllers.Workspace);
59118             app.zephyr.controller('historyController', app.controllers.History);
59119             app.zephyr.controller('commandController', app.directives.CommandController);
59120             app.zephyr.controller('optionController', app.directives.OptionController);
59121             app.zephyr.controller('directoryController', app.directives.DirectoryController);
59122             app.zephyr.controller('HeaderMenuController', app.directives.HeaderMenuController);
59123 <<<<<<< HEAD
59124             app.zephyr.controller('uploadController', app.directives.UploadController);
59125 =======
59126 >>>>>>> 6b2b2b88511733893d2c6e7848c389abfcd53ba6
59127             app.zephyr.directive('headerMenu', app.directives.HeaderMenu.Factory());
59128             app.zephyr.directive('command', app.directives.Command.Factory());
59129             app.zephyr.directive('option', app.directives.Option.Factory());
59130             app.zephyr.directive('directory', app.directives.Directory.Factory());
59131         })(app || (app = {}));
59132
59133
59134 /***/ }
59135 /******/ ]);